ERC20.sol
1 pragma solidity >=0.6.0; 2 3 import "../interfaces/IERC20.sol"; 4 import "../interfaces/IERC20Details.sol"; 5 import "../interfaces/IERC20Permit.sol"; 6 import "../utils/SafeMath.sol"; 7 8 abstract contract ERC20 is IERC20, IERC20Details, IERC20Permit { 9 10 using SafeMath for uint; 11 12 mapping(address => uint) balances; 13 mapping(address => mapping(address => uint)) allowed; 14 mapping(address => uint) public nonces; 15 16 bytes32 public DOMAIN_SEPARATOR; 17 // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); 18 bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; 19 20 uint _totalSupply; 21 22 constructor(string memory _name) public { 23 24 uint chainId; 25 assembly { 26 chainId := chainid() 27 } 28 DOMAIN_SEPARATOR = keccak256( 29 abi.encode( 30 keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), 31 keccak256(bytes(_name)), 32 keccak256(bytes('1')), 33 chainId, 34 address(this) 35 ) 36 ); 37 } 38 39 function decimals() override virtual external view returns (uint8) { 40 return 18; 41 } 42 43 function totalSupply() override virtual public view returns (uint) { 44 return _totalSupply; 45 } 46 47 function balanceOf(address owner) override virtual public view returns (uint) { 48 return balances[owner]; 49 } 50 51 function allowance(address owner, address spender) override public view returns (uint) { 52 53 return allowed[owner][spender]; 54 } 55 56 function transfer(address to, uint value) override virtual external returns (bool) { 57 58 require(value <= balanceOf(msg.sender)); 59 require(to != address(0)); 60 61 removeBalance(msg.sender, value); 62 addBalance(to, value); 63 emitTransfer(msg.sender, to, value); 64 return true; 65 } 66 67 function approve(address spender, uint value) override external returns (bool) { 68 69 return approve(msg.sender, spender, value); 70 } 71 72 function transferFrom(address from, address to, uint value) override virtual public returns (bool) { 73 74 require(value <= balanceOf(from)); 75 require(value <= allowed[from][msg.sender]); 76 require(to != address(0)); 77 78 removeBalance(from, value); 79 addBalance(to, value); 80 allowed[from][msg.sender] = allowed[from][msg.sender].sub(value); 81 emitTransfer(from, to, value); 82 return true; 83 } 84 85 function permit( 86 address owner, 87 address spender, 88 uint value, 89 uint deadline, 90 uint8 v, 91 bytes32 r, 92 bytes32 s 93 ) 94 override 95 external 96 { 97 require(deadline >= block.timestamp, "permit expired"); 98 bytes32 digest = keccak256( 99 abi.encodePacked( 100 "\x19\x01", 101 DOMAIN_SEPARATOR, 102 keccak256( 103 abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline) 104 ) 105 ) 106 ); 107 address recoveredAddress = ecrecover(digest, v, r, s); 108 require(recoveredAddress != address(0) && recoveredAddress == owner, "invalid signature"); 109 approve(owner, spender, value); 110 } 111 112 function approve(address owner, address spender, uint value) private returns (bool) { 113 114 require(spender != address(0)); 115 116 allowed[owner][spender] = value; 117 emitApproval(owner, spender, value); 118 return true; 119 } 120 121 function addBalance(address owner, uint value) virtual internal { 122 123 balances[owner] = balanceOf(owner).add(value); 124 } 125 126 function removeBalance(address owner, uint value) virtual internal { 127 128 balances[owner] = balanceOf(owner).sub(value); 129 } 130 131 function emitTransfer(address from, address to, uint value) virtual internal { 132 133 emit Transfer(from, to, value); 134 } 135 136 function emitApproval(address owner, address spender, uint value) virtual internal { 137 138 emit Approval(owner, spender, value); 139 } 140 }