ERC20
WEB3DEV Team
# ERC20
Todo contrato que segue o ERC20 standard (opens new window) é um token ERC20.
Tokens ERC20 fornecem funcionalidades para
- transferir tokens
- permitir que outros transfiram tokens em nome do titular do token
Eis aqui a interface para ERC20.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/token/ERC20/IERC20.sol
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(
address remetente,
address destinatario,
uint quantidade
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
Exemplo de um contrato de token ERC20.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./IERC20.sol";
contract ERC20 is IERC20 {
uint public totalSupply;
mapping(address => uint) public balanceOf;
mapping(address => mapping(address => uint)) public allowance;
string public name = "Solidity by Example";
string public symbol = "SOLBYEX";
uint8 public decimals = 18;
function transfer(address recipient, uint amount) external returns (bool) {
balanceOf[msg.sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint amount) external returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(
address remetente,
address destinatario,
uint quantidade
) external returns (bool) {
allowance[sender][msg.sender] -= amount;
balanceOf[sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
function mint(uint amount) external {
balanceOf[msg.sender] += amount;
totalSupply += amount;
emit Transfer(address(0), msg.sender, amount);
}
function burn(uint amount) external {
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
emit Transfer(msg.sender, address(0), amount);
}
}
# Crie seu próprio token ERC20
Usando Open Zeppelin (opens new window) é muito fácil criar seu próprio token ERC20.
Eis aqui um exemplo
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.0.0/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor(string memory name, string memory symbol) ERC20(name, symbol) {
// Mint 100 tokens para msg.sender
// Semelhante a como
// 1 real = 100 centavos
// 1 token = 1 * (10 ** decimals)
_mint(msg.sender, 100 * 10**uint(decimals()));
}
}
# Contrato para trocar tokens
Aqui está um exemplo de contrato, TokenSwap
, para trocar um token ERC20 por outro.
Este contrato negociará tokens chamando
transferFrom(address remetente, address destinatario, uint256 quantidade)
que irá transferir uma quantidade
de token do remetente
para o destinatario
.
Para transferFrom
ter sucesso, o remetente deve
- A
quantidade
de tokens no seu saldo deve ser maior do que está enviando - permitir
TokenSwap
para retirar umaquantidade
de tokens chamandoapprove
antes do TokenSwap
chamar transferFrom
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.0.0/contracts/token/ERC20/IERC20.sol";
/*
Como trocar tokens
1. Alice tem 100 tokens de AliceCoin, que é um token ERC20.
2. Bob tem 100 tokens de BobCoin, que também é um token ERC20.
3. Alice e Bob querem negociar 10 AliceCoin por 20 BobCoin.
4. Alice ou Bob implantam TokenSwap
5. Alice aprova TokenSwap para retirar 10 tokens de AliceCoin
6. Bob aprova TokenSwap para retirar 20 tokens de BobCoin
7. Alice ou Bob chamam TokenSwap.swap()
8. Alice e Bob negociaram tokens com sucesso.
*/
contract TokenSwap {
IERC20 public token1;
address public owner1;
uint public amount1;
IERC20 public token2;
address public owner2;
uint public amount2;
constructor(
address _token1,
address _owner1,
uint _amount1,
address _token2,
address _owner2,
uint _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,
"Token 1 allowance too low"
);
require(
token2.allowance(owner2, address(this)) >= amount2,
"Token 2 allowance too low"
);
_safeTransferFrom(token1, owner1, owner2, amount1);
_safeTransferFrom(token2, owner2, owner1, amount2);
}
function _safeTransferFrom(
IERC20 token,
address sender,
address recipient,
uint amount
) private {
bool sent = token.transferFrom(sender, recipient, amount);
require(sent, "Token transfer failed");
}
}