欢迎订阅专栏:3分钟Solidity--智能合约--Web3区块链技术必学
如需获取本内容的最新版本,请参见 Cyfrin.io 上的ERC20(代码示例)
任何遵循ERC20标准的合约都是ERC20代币。
ERC-20引入了可替代Token(代币)的标准,换句话说,它们具有使每个Token(代币)与另一个Token(代币)完全相同(在类型和价值上)的属性。例如,ERC-20,Token(代币)的行为与ETH相同,这意味着任意1个遵循ERC-20规则的Token(代币)与所有其他所有Token(代币)是平等和相同的。
ERC20代币提供以下功能:
- 转移代币
- 允许他人代表代币持有者转移代币
以下是ERC20的接口。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount)
external
returns (bool);
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount)
external
returns (bool);
}
ERC20代币合约示例。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "./IERC20.sol";
contract ERC20 is IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner, address indexed spender, uint256 value
);
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
string public name;
string public symbol;
uint8 public decimals;
constructor(string memory _name, string memory _symbol, uint8 _decimals) {
name = _name;
symbol = _symbol;
decimals = _decimals;
}
function transfer(address recipient, uint256 amount)
external
returns (bool)
{
balanceOf[msg.sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) external returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount)
external
returns (bool)
{
allowance[sender][msg.sender] -= amount;
balanceOf[sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
function _mint(address to, uint256 amount) internal {
balanceOf[to] += amount;
totalSupply += amount;
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal {
balanceOf[from] -= amount;
totalSupply -= amount;
emit Transfer(from, address(0), amount);
}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
function burn(address from, uint256 amount) external {
_burn(from, amount);
}
}
创建你自己的ERC20代币
使用Open Zeppelin可以非常轻松地创建你自己的ERC20代币。
这里有一个示例
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "./ERC20.sol";
contract MyToken is ERC20 {
constructor(string memory name, string memory symbol, uint8 decimals)
ERC20(name, symbol, decimals)
{
// Mint 100 tokens to msg.sender
// Similar to how
// 1 dollar = 100 cents
// 1 token = 1 * (10 ** decimals)
_mint(msg.sender, 100 * 10 ** uint256(decimals));
}
}
代币交换合约
以下是一个示例合约 TokenSwap,用于将一个 ERC20 代币兑换为另一个 ERC20 代币。
该合约将通过调用以下功能实现代币交换:
transferFrom(address sender, address recipient, uint256 amount)
该操作会将 amount数量的代币从 sender转账至 recipient。
要使 transferFrom执行成功,sender必须满足以下条件:
- 账户余额需大于
amount数量的代币 - 在
TokenSwap调用transferFrom之前,已通过调用approve授权TokenSwap提取amount数量的代币
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "./IERC20.sol";
/*
如何交换代币
1. Alice拥有100个AliceCoin代币,这是一种ERC20代币。
2. Bob拥有100个BobCoin代币,这也是一种ERC20代币。
3. Alice和Bob想用10个AliceCoin交换20个BobCoin。
4. Alice或Bob部署TokenSwap合约
5. Alice授权TokenSwap合约从AliceCoin中提取10个代币
6. Bob授权TokenSwap合约从BobCoin中提取20个代币
7. Alice或Bob调用TokenSwap.swap()方法
8. Alice和Bob成功完成了代币交换。
*/
contract TokenSwap {
IERC20 public token1;
address public owner1;
uint256 public amount1;
IERC20 public token2;
address public owner2;
uint256 public amount2;
constructor(
address _token1,
address _owner1,
uint256 _amount1,
address _token2,
address _owner2,
uint256 _amount2
) {
token1 = IERC20(_token1);
owner1 = _owner1;
amount1 = _amount1;
token2 = IERC20(_token2);
owner2 = _owner2;
amount2 = _amount2;
}
function swap() public {
require(msg.sender == owner1 || msg.sender == owner2, "Not authorized");
require(
token1.allowance(owner1, address(this)) >= amount1,
"代币1的授权额度过低"
);
require(
token2.allowance(owner2, address(this)) >= amount2,
"代币2限额过低"
);
_safeTransferFrom(token1, owner1, owner2, amount1);
_safeTransferFrom(token2, owner2, owner1, amount2);
}
function _safeTransferFrom(
IERC20 token,
address sender,
address recipient,
uint256 amount
) private {
bool sent = token.transferFrom(sender, recipient, amount);
require(sent, "Token transfer failed");
}
}
Remix Lite 尝试一下