和区块链Say Hi(6)--- 通过Remix发布以太坊Solidity智能合约

我们来学习一下如何通过Remix发布一个简单的ERC20智能合约。以下操作都是基于ETH Sepolia测试网来进行的。

1.打开Remix工具

https://remix.ethereum.org/
在这里插入图片描述
在这里插入图片描述

2.贴上智能合约代码

这里的智能合约只是简单地mint一个ERC20的数字货币

//SPDX-License-Identifier: UNLICENSED

pragma solidity >=0.4.22<0.9.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract JokerCoin is ERC20 {

constructor() ERC20("JokerCoin", "JOKER") {

_mint(msg.sender, 100000000000000000000000000);

}

}

3.编译智能合约

在这里插入图片描述

4.连接钱包

这里选择的是MetaMask小狐狸钱包,关联钱包地址
在这里插入图片描述

5.水龙头网站领取测试代币

上面可以看到当前钱包地址是余额是0,发布智能合约需要手续费gas,所以我们通过水龙头网站领取一下测试代币。
https://www.alchemy.com/faucets/ethereum-sepolia
在这里插入图片描述
领取后:
在这里插入图片描述

6.发布智能合约

在这里插入图片描述

7.相关信息确认

交易信息:

https://sepolia.etherscan.io/tx/0x03d3475779a042d29465c0be0768cbef7d818575b34e786c9560dff51c7f553d
在这里插入图片描述

查看对应钱包地址:
在这里插入图片描述

智能合约:
https://sepolia.etherscan.io/token/0xde8d49a648e425a7e1de70e7030bc566581d9e49?a=0x55c37ba076187fdf42863951e5252c8e15f0a47e

在这里插入图片描述

8.简单的智能合约案例

案例一:

// SPDX-License-Identifier: MIT
pragma solidity >=0.6.12 <0.9.0;

contract BlackHole {
    string public constant name = "BlackHole"; // 数字货币名称
    string public constant symbol = "BH"; // 数字货币符号
    uint8 public constant decimals = 18; // 小数位数,与以太币相同
    uint256 public totalSupply = 100000000 * (10 ** uint256(decimals)); // 初始总供应量,100000000 个 BlackHole
    mapping(address => uint256) public balanceOf; // 用户余额映射
    address public blackHoleAccount; // 黑洞账户地址

    // 事件,用于记录转账操作
    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    // 构造函数,在部署合约时初始化黑洞账户
    constructor() {
        blackHoleAccount = 0x8Ae4BA8e6cB6b9F9A155Cafb5FAd558A4D253cf2;
        balanceOf[msg.sender] = totalSupply;
    }


    // 转账函数,每次交易都会将交易金额的1%转移到黑洞账户
    function transfer(address _to, uint256 _value) public returns (bool success) {
        require(_to != address(0)); // 检查目标地址是否合法
        require(balanceOf[msg.sender] >= _value); // 检查发送者余额是否足够
        require(balanceOf[_to] + _value >= balanceOf[_to]); // 检查溢出

        uint256 amountToBlackHole = _value / 100; // 交易金额的1%
        uint256 amountToRecipient = _value - amountToBlackHole; // 交易金额减去转移到黑洞账户的部分

        balanceOf[msg.sender] -= _value; // 扣除发送者余额
        balanceOf[_to] += amountToRecipient; // 增加接收者余额
        balanceOf[blackHoleAccount] += amountToBlackHole; // 增加黑洞账户余额

        emit Transfer(msg.sender, _to, amountToRecipient); // 记录转账到接收者的交易
        emit Transfer(msg.sender, blackHoleAccount, amountToBlackHole); // 记录转移到黑洞账户的交易

        return true;
    }
}

案例二:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// 导入 OpenZeppelin 中的 ERC20 合约,用于创建代币
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
// 导入 OpenZeppelin 中的 Ownable 合约,用于实现权限控制
import "@openzeppelin/contracts/access/Ownable.sol";
// 导入 OpenZeppelin 中的 SafeMath 库,用于安全的数学运算
import "@openzeppelin/contracts/utils/math/SafeMath.sol";

// 定义 DeFiToken 合约,继承 ERC20 合约和 Ownable 合约
contract DeFiToken is ERC20, Ownable {
    using SafeMath for uint256; // 使用 SafeMath 库来进行安全的数学运算

    uint256 public constant TOTAL_SUPPLY = 100000000 * (10 ** 18); // 初始总供应量为 100000000 枚

    uint256 public ANNUAL_INTEREST_RATE; // 年利率
    uint256 public DAILY_INTEREST_RATE; // 日利率

    // 定义映射,用于存储用户的存款金额和存款时间戳
    mapping(address => uint256) public depositedAmount;
    mapping(address => uint256) public depositTimestamp;

    // 定义事件,用于记录存款和提款操作
    event Deposit(address indexed user, uint256 amount); // 存款事件
    event Withdrawal(address indexed user, uint256 amount); // 提款事件

    // 合约构造函数,初始化 DeFiToken 合约,分发总供应量给合约创建者,并设置初始利率
    constructor(address initialOwner) ERC20("DeFi Token", "DEFI") Ownable(initialOwner) {
        _mint(msg.sender, TOTAL_SUPPLY); // 在构造函数中调用 _mint 函数,向合约创建者分发总供应量的代币

        // 初始化利率为 30% 的年利率和 1% 的日利率
        ANNUAL_INTEREST_RATE = 30;
        DAILY_INTEREST_RATE = 1;
    }

    // 存款函数,允许用户将代币存入合约
    function deposit(uint256 _amount) external {
        require(_amount > 0, "Amount must be greater than 0"); // 断言:检查存款金额是否大于 0
        require(balanceOf(msg.sender) >= _amount, "Insufficient balance"); // 断言:检查用户余额是否足够
        
        // 调用 ERC20 合约的 transferFrom 方法,将代币转移到合约地址
        transferFrom(msg.sender, address(this), _amount);

        // 更新存款记录
        depositedAmount[msg.sender] = depositedAmount[msg.sender].add(_amount);
        depositTimestamp[msg.sender] = block.timestamp; // 存储当前区块的时间戳作为存款时间

        // 触发 Deposit 事件,记录存款操作
        emit Deposit(msg.sender, _amount);
    }

    // 提款函数,允许用户从合约提取存款及利息
    function withdraw(uint256 _amount) external {
        require(_amount > 0, "Amount must be greater than 0"); // 断言:检查提款金额是否大于 0
        require(depositedAmount[msg.sender] >= _amount, "Insufficient deposited amount"); // 断言:检查用户存款是否足够

        // 计算应得利息并计算总提款金额
        uint256 interest = calculateInterest(msg.sender);
        uint256 totalWithdrawAmount = _amount.add(interest);

        // 调用 ERC20 合约的 transfer 方法,将代币转移给用户
        transfer(msg.sender, totalWithdrawAmount);

        // 更新存款记录
        depositedAmount[msg.sender] = depositedAmount[msg.sender].sub(_amount);
        depositTimestamp[msg.sender] = block.timestamp;

        // 触发 Withdrawal 事件,记录提款操作
        emit Withdrawal(msg.sender, totalWithdrawAmount);
    }

    // 查询用户余额函数
    function getBalance(address _user) external view returns (uint256) {
        return balanceOf(_user); // 返回用户的代币余额
    }

    // 计算利息函数
    function calculateInterest(address _user) internal view returns (uint256) {
        // 计算存款时间
        uint256 depositedTime = block.timestamp.sub(depositTimestamp[_user]);
        uint256 daysElapsed = depositedTime.div(1 days); // 将时间差转换为天数

        // 计算利息并返回
        return depositedAmount[_user].mul(ANNUAL_INTEREST_RATE).mul(daysElapsed).div(36500); // 年利率转换为每天的利率
    }

    // 设置利率函数,只有合约所有者可以调用
    function setInterestRate(uint256 _annualInterestRate, uint256 _dailyInterestRate) external onlyOwner {
        require(_annualInterestRate > 0 && _dailyInterestRate > 0, "Interest rate must be greater than 0");

        // 更新年利率和日利率
        ANNUAL_INTEREST_RATE = _annualInterestRate;
        DAILY_INTEREST_RATE = _dailyInterestRate;
    }

    // 接收以太币函数,防止用户直接向合约地址发送代币
    receive() external payable {
        revert("Direct deposits are not allowed");
    }

    // 提供转移误转入合约的以太币给合约所有者的方法
    function withdrawEther(uint256 _amount) external onlyOwner {
        payable(owner()).transfer(_amount);
    }
}

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lucarun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值