// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract BaseERC20 {
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowances;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor() public {
// write your code here
// set name,symbol,decimals,totalSupply
name="BaseERC20";
symbol="BERC20";
decimals=18;
totalSupply=100000000*(10**uint256(18));
balances[msg.sender] = totalSupply;
}
function balanceOf(address _owner) public view returns (uint256 balance) {
// write your code here
return balances[_owner];
}
function transfer(address _to, uint256 _value) public returns (bool success) {
// write your code here
require(balances[msg.sender]>=_value,"ERC20: transfer amount exceeds balance");
balances[msg.sender]-=_value;
balances[_to]+=_value;
emit Transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
// write your code here
require(balances[_from]>=_value,"ERC20: transfer amount exceeds balance");
require(allowances[_from][msg.sender]>=_value,"ERC20: transfer amount exceeds allowance");
allowances[_from][msg.sender]-=_value;
balances[_from]-=_value;
balances[_to]+=_value;
emit Transfer(_from, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) public returns (bool success) {
// write your code here
allowances[msg.sender][_spender]=_value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
// write your code here
return allowances[_owner][_spender];
}
}
ERC20的难点我觉得主要在于transferFrom这个函数。看openzeppelin的官方实现,transferFrom这个函数被msg.sender调用,用于_from给_to转账。也就是说,msg.sender可以用_from给msg.sender的额度,给_to转账。一开始我以为这个是扣_to的额度,但并不是的,扣的是调用者msg.sender的额度。简单来说,就是msg.sender可以使用_from给自己的额度,然后给任意一个地址(_to)转账。