/ contracts / utils / ERC20.sol
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  }