├── inSure.sol └── inSureBSCAnySwap.sol /inSure.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.16; 2 | 3 | interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; } 4 | // --- 5 | 6 | 7 | contract TokenERC20 { 8 | string public name="inSure"; 9 | string public symbol="SURE"; 10 | uint8 public decimals = 18; 11 | // 18 decimals is the strongly suggested default, avoid changing it 12 | uint256 public totalSupply=88000000000000000000000000000; 13 | // This creates an array with all balances 14 | mapping (address => uint256) public balanceOf; 15 | mapping (address => mapping (address => uint256)) public allowance; 16 | 17 | // This generates a public event on the blockchain that will notify clients 18 | event Transfer(address indexed from, address indexed to, uint256 value); 19 | 20 | // This notifies clients about the amount burnt 21 | event Burn(address indexed from, uint256 value); 22 | 23 | /** 24 | * Constrctor function 25 | * 26 | * Initializes contract with initial supply tokens to the creator of the contract 27 | */ 28 | function TokenERC20( 29 | uint256 initialSupply, 30 | string tokenName, 31 | string tokenSymbol 32 | ) public { 33 | totalSupply = initialSupply * 10 ** uint256(decimals); // Update total supply with the decimal amount 34 | balanceOf[msg.sender] = totalSupply; // Give the creator all initial tokens 35 | name = tokenName; // Set the name for display purposes 36 | symbol = tokenSymbol; // Set the symbol for display purposes 37 | } 38 | 39 | /** 40 | * Internal transfer, only can be called by this contract 41 | */ 42 | function _transfer(address _from, address _to, uint _value) internal { 43 | // Prevent transfer to 0x0 address. Use burn() instead 44 | require(_to != 0x0); 45 | // Check if the sender has enough 46 | require(balanceOf[_from] >= _value); 47 | // Check for overflows 48 | require(balanceOf[_to] + _value > balanceOf[_to]); 49 | // Save this for an assertion in the future 50 | uint previousBalances = balanceOf[_from] + balanceOf[_to]; 51 | // Subtract from the sender 52 | balanceOf[_from] -= _value; 53 | // Add the same to the recipient 54 | balanceOf[_to] += _value; 55 | Transfer(_from, _to, _value); 56 | // Asserts are used to use static analysis to find bugs in your code. They should never fail 57 | assert(balanceOf[_from] + balanceOf[_to] == previousBalances); 58 | } 59 | 60 | /** 61 | * Transfer tokens 62 | * 63 | * Send `_value` tokens to `_to` from your account 64 | * 65 | * @param _to The address of the recipient 66 | * @param _value the amount to send 67 | */ 68 | function transfer(address _to, uint256 _value) public { 69 | _transfer(msg.sender, _to, _value); 70 | } 71 | 72 | /** 73 | * Transfer tokens from other address 74 | * 75 | * Send `_value` tokens to `_to` in behalf of `_from` 76 | * 77 | * @param _from The address of the sender 78 | * @param _to The address of the recipient 79 | * @param _value the amount to send 80 | */ 81 | function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { 82 | require(_value <= allowance[_from][msg.sender]); // Check allowance 83 | allowance[_from][msg.sender] -= _value; 84 | _transfer(_from, _to, _value); 85 | return true; 86 | } 87 | 88 | /** 89 | * Set allowance for other address 90 | * 91 | * Allows `_spender` to spend no more than `_value` tokens in your behalf 92 | * 93 | * @param _spender The address authorized to spend 94 | * @param _value the max amount they can spend 95 | */ 96 | function approve(address _spender, uint256 _value) public 97 | returns (bool success) { 98 | allowance[msg.sender][_spender] = _value; 99 | return true; 100 | } 101 | 102 | /** 103 | * Set allowance for other address and notify 104 | * 105 | * Allows `_spender` to spend no more than `_value` tokens in your behalf, and then ping the contract about it 106 | * 107 | * @param _spender The address authorized to spend 108 | * @param _value the max amount they can spend 109 | * @param _extraData some extra information to send to the approved contract 110 | */ 111 | function approveAndCall(address _spender, uint256 _value, bytes _extraData) 112 | public 113 | returns (bool success) { 114 | tokenRecipient spender = tokenRecipient(_spender); 115 | if (approve(_spender, _value)) { 116 | spender.receiveApproval(msg.sender, _value, this, _extraData); 117 | return true; 118 | } 119 | } 120 | 121 | /** 122 | * Destroy tokens 123 | * 124 | * Remove `_value` tokens from the system irreversibly 125 | * 126 | * @param _value the amount of money to burn 127 | */ 128 | function burn(uint256 _value) public returns (bool success) { 129 | require(balanceOf[msg.sender] >= _value); // Check if the sender has enough 130 | balanceOf[msg.sender] -= _value; // Subtract from the sender 131 | totalSupply -= _value; // Updates totalSupply 132 | Burn(msg.sender, _value); 133 | return true; 134 | } 135 | 136 | /** 137 | * Destroy tokens from other account 138 | * 139 | * Remove `_value` tokens from the system irreversibly on behalf of `_from`. 140 | * 141 | * @param _from the address of the sender 142 | * @param _value the amount of money to burn 143 | */ 144 | function burnFrom(address _from, uint256 _value) public returns (bool success) { 145 | require(balanceOf[_from] >= _value); // Check if the targeted balance is enough 146 | require(_value <= allowance[_from][msg.sender]); // Check allowance 147 | balanceOf[_from] -= _value; // Subtract from the targeted balance 148 | allowance[_from][msg.sender] -= _value; // Subtract from the sender's allowance 149 | totalSupply -= _value; // Update totalSupply 150 | Burn(_from, _value); 151 | return true; 152 | } 153 | 154 | } 155 | -------------------------------------------------------------------------------- /inSureBSCAnySwap.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at BscScan.com on 2021-03-23 3 | */ 4 | 5 | // SPDX-License-Identifier: GPL-3.0-or-later 6 | 7 | pragma solidity 0.8.2; 8 | 9 | /** 10 | * @dev Interface of the ERC20 standard as defined in the EIP. 11 | */ 12 | interface IERC20 { 13 | function totalSupply() external view returns (uint256); 14 | function decimals() external view returns (uint8); 15 | function balanceOf(address account) external view returns (uint256); 16 | function transfer(address recipient, uint256 amount) external returns (bool); 17 | function allowance(address owner, address spender) external view returns (uint256); 18 | function approve(address spender, uint256 amount) external returns (bool); 19 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 20 | function permit(address target, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; 21 | function transferWithPermit(address target, address to, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external returns (bool); 22 | event Transfer(address indexed from, address indexed to, uint256 value); 23 | event Approval(address indexed owner, address indexed spender, uint256 value); 24 | } 25 | 26 | /** 27 | * @dev Interface of the ERC2612 standard as defined in the EIP. 28 | * 29 | * Adds the {permit} method, which can be used to change one's 30 | * {IERC20-allowance} without having to send a transaction, by signing a 31 | * message. This allows users to spend tokens without having to hold Ether. 32 | * 33 | * See https://eips.ethereum.org/EIPS/eip-2612. 34 | */ 35 | interface IERC2612 { 36 | 37 | /** 38 | * @dev Returns the current ERC2612 nonce for `owner`. This value must be 39 | * included whenever a signature is generated for {permit}. 40 | * 41 | * Every successful call to {permit} increases ``owner``'s nonce by one. This 42 | * prevents a signature from being used multiple times. 43 | */ 44 | function nonces(address owner) external view returns (uint256); 45 | } 46 | 47 | /// @dev Wrapped ERC-20 v10 (AnyswapV3ERC20) is an ERC-20 ERC-20 wrapper. You can `deposit` ERC-20 and obtain an AnyswapV3ERC20 balance which can then be operated as an ERC-20 token. You can 48 | /// `withdraw` ERC-20 from AnyswapV3ERC20, which will then burn AnyswapV3ERC20 token in your wallet. The amount of AnyswapV3ERC20 token in any wallet is always identical to the 49 | /// balance of ERC-20 deposited minus the ERC-20 withdrawn with that specific wallet. 50 | interface IAnyswapV3ERC20 is IERC20, IERC2612 { 51 | 52 | /// @dev Sets `value` as allowance of `spender` account over caller account's AnyswapV3ERC20 token, 53 | /// after which a call is executed to an ERC677-compliant contract with the `data` parameter. 54 | /// Emits {Approval} event. 55 | /// Returns boolean value indicating whether operation succeeded. 56 | /// For more information on approveAndCall format, see https://github.com/ethereum/EIPs/issues/677. 57 | function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); 58 | 59 | /// @dev Moves `value` AnyswapV3ERC20 token from caller's account to account (`to`), 60 | /// after which a call is executed to an ERC677-compliant contract with the `data` parameter. 61 | /// A transfer to `address(0)` triggers an ERC-20 withdraw matching the sent AnyswapV3ERC20 token in favor of caller. 62 | /// Emits {Transfer} event. 63 | /// Returns boolean value indicating whether operation succeeded. 64 | /// Requirements: 65 | /// - caller account must have at least `value` AnyswapV3ERC20 token. 66 | /// For more information on transferAndCall format, see https://github.com/ethereum/EIPs/issues/677. 67 | function transferAndCall(address to, uint value, bytes calldata data) external returns (bool); 68 | } 69 | 70 | interface ITransferReceiver { 71 | function onTokenTransfer(address, uint, bytes calldata) external returns (bool); 72 | } 73 | 74 | interface IApprovalReceiver { 75 | function onTokenApproval(address, uint, bytes calldata) external returns (bool); 76 | } 77 | 78 | library Address { 79 | function isContract(address account) internal view returns (bool) { 80 | bytes32 codehash; 81 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 82 | // solhint-disable-next-line no-inline-assembly 83 | assembly { codehash := extcodehash(account) } 84 | return (codehash != 0x0 && codehash != accountHash); 85 | } 86 | } 87 | 88 | library SafeERC20 { 89 | using Address for address; 90 | 91 | function safeTransfer(IERC20 token, address to, uint value) internal { 92 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 93 | } 94 | 95 | function safeTransferFrom(IERC20 token, address from, address to, uint value) internal { 96 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 97 | } 98 | 99 | function safeApprove(IERC20 token, address spender, uint value) internal { 100 | require((value == 0) || (token.allowance(address(this), spender) == 0), 101 | "SafeERC20: approve from non-zero to non-zero allowance" 102 | ); 103 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 104 | } 105 | function callOptionalReturn(IERC20 token, bytes memory data) private { 106 | require(address(token).isContract(), "SafeERC20: call to non-contract"); 107 | 108 | // solhint-disable-next-line avoid-low-level-calls 109 | (bool success, bytes memory returndata) = address(token).call(data); 110 | require(success, "SafeERC20: low-level call failed"); 111 | 112 | if (returndata.length > 0) { // Return data is optional 113 | // solhint-disable-next-line max-line-length 114 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 115 | } 116 | } 117 | } 118 | 119 | contract AnyswapV4ERC20 is IAnyswapV3ERC20 { 120 | using SafeERC20 for IERC20; 121 | string public name; 122 | string public symbol; 123 | uint8 public immutable override decimals; 124 | 125 | address public immutable underlying; 126 | 127 | bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); 128 | bytes32 public constant TRANSFER_TYPEHASH = keccak256("Transfer(address owner,address to,uint256 value,uint256 nonce,uint256 deadline)"); 129 | bytes32 public immutable DOMAIN_SEPARATOR; 130 | 131 | /// @dev Records amount of AnyswapV3ERC20 token owned by account. 132 | mapping (address => uint256) public override balanceOf; 133 | uint256 private _totalSupply; 134 | 135 | // init flag for setting immediate vault, needed for CREATE2 support 136 | bool private _init; 137 | 138 | // flag to enable/disable swapout vs vault.burn so multiple events are triggered 139 | bool private _vaultOnly; 140 | 141 | // configurable delay for timelock functions 142 | uint public delay = 2*24*3600; 143 | 144 | 145 | // set of minters, can be this bridge or other bridges 146 | mapping(address => bool) public isMinter; 147 | address[] public minters; 148 | 149 | // primary controller of the token contract 150 | address public vault; 151 | 152 | address public pendingMinter; 153 | uint public delayMinter; 154 | 155 | address public pendingVault; 156 | uint public delayVault; 157 | 158 | uint public pendingDelay; 159 | uint public delayDelay; 160 | 161 | 162 | modifier onlyAuth() { 163 | require(isMinter[msg.sender], "AnyswapV4ERC20: FORBIDDEN"); 164 | _; 165 | } 166 | 167 | modifier onlyVault() { 168 | require(msg.sender == mpc(), "AnyswapV3ERC20: FORBIDDEN"); 169 | _; 170 | } 171 | 172 | function owner() public view returns (address) { 173 | return mpc(); 174 | } 175 | 176 | function mpc() public view returns (address) { 177 | if (block.timestamp >= delayVault) { 178 | return pendingVault; 179 | } 180 | return vault; 181 | } 182 | 183 | function setVaultOnly(bool enabled) external onlyVault { 184 | _vaultOnly = enabled; 185 | } 186 | 187 | function initVault(address _vault) external onlyVault { 188 | require(_init); 189 | vault = _vault; 190 | pendingVault = _vault; 191 | isMinter[_vault] = true; 192 | minters.push(_vault); 193 | delayVault = block.timestamp; 194 | _init = false; 195 | } 196 | 197 | function setMinter(address _auth) external onlyVault { 198 | pendingMinter = _auth; 199 | delayMinter = block.timestamp + delay; 200 | } 201 | 202 | function setVault(address _vault) external onlyVault { 203 | pendingVault = _vault; 204 | delayVault = block.timestamp + delay; 205 | } 206 | 207 | function applyVault() external onlyVault { 208 | require(block.timestamp >= delayVault); 209 | vault = pendingVault; 210 | } 211 | 212 | function applyMinter() external onlyVault { 213 | require(block.timestamp >= delayMinter); 214 | isMinter[pendingMinter] = true; 215 | minters.push(pendingMinter); 216 | } 217 | 218 | // No time delay revoke minter emergency function 219 | function revokeMinter(address _auth) external onlyVault { 220 | isMinter[_auth] = false; 221 | } 222 | 223 | function getAllMinters() external view returns (address[] memory) { 224 | return minters; 225 | } 226 | 227 | 228 | function changeVault(address newVault) external onlyVault returns (bool) { 229 | require(newVault != address(0), "AnyswapV3ERC20: address(0x0)"); 230 | pendingVault = newVault; 231 | delayVault = block.timestamp + delay; 232 | emit LogChangeVault(vault, pendingVault, delayVault); 233 | return true; 234 | } 235 | 236 | function changeMPCOwner(address newVault) public onlyVault returns (bool) { 237 | require(newVault != address(0), "AnyswapV3ERC20: address(0x0)"); 238 | pendingVault = newVault; 239 | delayVault = block.timestamp + delay; 240 | emit LogChangeMPCOwner(vault, pendingVault, delayVault); 241 | return true; 242 | } 243 | 244 | function mint(address to, uint256 amount) external onlyAuth returns (bool) { 245 | _mint(to, amount); 246 | return true; 247 | } 248 | 249 | function burn(address from, uint256 amount) external onlyAuth returns (bool) { 250 | require(from != address(0), "AnyswapV3ERC20: address(0x0)"); 251 | _burn(from, amount); 252 | return true; 253 | } 254 | 255 | function Swapin(bytes32 txhash, address account, uint256 amount) public onlyAuth returns (bool) { 256 | _mint(account, amount); 257 | emit LogSwapin(txhash, account, amount); 258 | return true; 259 | } 260 | 261 | function Swapout(uint256 amount, address bindaddr) public returns (bool) { 262 | require(!_vaultOnly, "AnyswapV4ERC20: onlyAuth"); 263 | require(bindaddr != address(0), "AnyswapV3ERC20: address(0x0)"); 264 | _burn(msg.sender, amount); 265 | emit LogSwapout(msg.sender, bindaddr, amount); 266 | return true; 267 | } 268 | 269 | /// @dev Records current ERC2612 nonce for account. This value must be included whenever signature is generated for {permit}. 270 | /// Every successful call to {permit} increases account's nonce by one. This prevents signature from being used multiple times. 271 | mapping (address => uint256) public override nonces; 272 | 273 | /// @dev Records number of AnyswapV3ERC20 token that account (second) will be allowed to spend on behalf of another account (first) through {transferFrom}. 274 | mapping (address => mapping (address => uint256)) public override allowance; 275 | 276 | event LogChangeVault(address indexed oldVault, address indexed newVault, uint indexed effectiveTime); 277 | event LogChangeMPCOwner(address indexed oldOwner, address indexed newOwner, uint indexed effectiveHeight); 278 | event LogSwapin(bytes32 indexed txhash, address indexed account, uint amount); 279 | event LogSwapout(address indexed account, address indexed bindaddr, uint amount); 280 | event LogAddAuth(address indexed auth, uint timestamp); 281 | 282 | constructor(string memory _name, string memory _symbol, uint8 _decimals, address _underlying, address _vault) { 283 | name = _name; 284 | symbol = _symbol; 285 | decimals = _decimals; 286 | underlying = _underlying; 287 | if (_underlying != address(0x0)) { 288 | require(_decimals == IERC20(_underlying).decimals()); 289 | } 290 | 291 | // Use init to allow for CREATE2 accross all chains 292 | _init = true; 293 | 294 | // Disable/Enable swapout for v1 tokens vs mint/burn for v3 tokens 295 | _vaultOnly = false; 296 | 297 | vault = _vault; 298 | pendingVault = _vault; 299 | delayVault = block.timestamp; 300 | 301 | uint256 chainId; 302 | assembly {chainId := chainid()} 303 | DOMAIN_SEPARATOR = keccak256( 304 | abi.encode( 305 | keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), 306 | keccak256(bytes(name)), 307 | keccak256(bytes("1")), 308 | chainId, 309 | address(this))); 310 | } 311 | 312 | /// @dev Returns the total supply of AnyswapV3ERC20 token as the ETH held in this contract. 313 | function totalSupply() external view override returns (uint256) { 314 | return _totalSupply; 315 | } 316 | 317 | function depositWithPermit(address target, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s, address to) external returns (uint) { 318 | IERC20(underlying).permit(target, address(this), value, deadline, v, r, s); 319 | IERC20(underlying).safeTransferFrom(target, address(this), value); 320 | return _deposit(value, to); 321 | } 322 | 323 | function depositWithTransferPermit(address target, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s, address to) external returns (uint) { 324 | IERC20(underlying).transferWithPermit(target, address(this), value, deadline, v, r, s); 325 | return _deposit(value, to); 326 | } 327 | 328 | function deposit() external returns (uint) { 329 | uint _amount = IERC20(underlying).balanceOf(msg.sender); 330 | IERC20(underlying).safeTransferFrom(msg.sender, address(this), _amount); 331 | return _deposit(_amount, msg.sender); 332 | } 333 | 334 | function deposit(uint amount) external returns (uint) { 335 | IERC20(underlying).safeTransferFrom(msg.sender, address(this), amount); 336 | return _deposit(amount, msg.sender); 337 | } 338 | 339 | function deposit(uint amount, address to) external returns (uint) { 340 | IERC20(underlying).safeTransferFrom(msg.sender, address(this), amount); 341 | return _deposit(amount, to); 342 | } 343 | 344 | function depositVault(uint amount, address to) external onlyVault returns (uint) { 345 | return _deposit(amount, to); 346 | } 347 | 348 | function _deposit(uint amount, address to) internal returns (uint) { 349 | require(underlying != address(0x0) && underlying != address(this)); 350 | _mint(to, amount); 351 | return amount; 352 | } 353 | 354 | function withdraw() external returns (uint) { 355 | return _withdraw(msg.sender, balanceOf[msg.sender], msg.sender); 356 | } 357 | 358 | function withdraw(uint amount) external returns (uint) { 359 | return _withdraw(msg.sender, amount, msg.sender); 360 | } 361 | 362 | function withdraw(uint amount, address to) external returns (uint) { 363 | return _withdraw(msg.sender, amount, to); 364 | } 365 | 366 | function withdrawVault(address from, uint amount, address to) external onlyVault returns (uint) { 367 | return _withdraw(from, amount, to); 368 | } 369 | 370 | function _withdraw(address from, uint amount, address to) internal returns (uint) { 371 | _burn(from, amount); 372 | IERC20(underlying).safeTransfer(to, amount); 373 | return amount; 374 | } 375 | 376 | /** @dev Creates `amount` tokens and assigns them to `account`, increasing 377 | * the total supply. 378 | * 379 | * Emits a {Transfer} event with `from` set to the zero address. 380 | * 381 | * Requirements 382 | * 383 | * - `to` cannot be the zero address. 384 | */ 385 | function _mint(address account, uint256 amount) internal { 386 | require(account != address(0), "ERC20: mint to the zero address"); 387 | 388 | _totalSupply += amount; 389 | balanceOf[account] += amount; 390 | emit Transfer(address(0), account, amount); 391 | } 392 | 393 | /** 394 | * @dev Destroys `amount` tokens from `account`, reducing the 395 | * total supply. 396 | * 397 | * Emits a {Transfer} event with `to` set to the zero address. 398 | * 399 | * Requirements 400 | * 401 | * - `account` cannot be the zero address. 402 | * - `account` must have at least `amount` tokens. 403 | */ 404 | function _burn(address account, uint256 amount) internal { 405 | require(account != address(0), "ERC20: burn from the zero address"); 406 | 407 | balanceOf[account] -= amount; 408 | _totalSupply -= amount; 409 | emit Transfer(account, address(0), amount); 410 | } 411 | 412 | /// @dev Sets `value` as allowance of `spender` account over caller account's AnyswapV3ERC20 token. 413 | /// Emits {Approval} event. 414 | /// Returns boolean value indicating whether operation succeeded. 415 | function approve(address spender, uint256 value) external override returns (bool) { 416 | // _approve(msg.sender, spender, value); 417 | allowance[msg.sender][spender] = value; 418 | emit Approval(msg.sender, spender, value); 419 | 420 | return true; 421 | } 422 | 423 | /// @dev Sets `value` as allowance of `spender` account over caller account's AnyswapV3ERC20 token, 424 | /// after which a call is executed to an ERC677-compliant contract with the `data` parameter. 425 | /// Emits {Approval} event. 426 | /// Returns boolean value indicating whether operation succeeded. 427 | /// For more information on approveAndCall format, see https://github.com/ethereum/EIPs/issues/677. 428 | function approveAndCall(address spender, uint256 value, bytes calldata data) external override returns (bool) { 429 | // _approve(msg.sender, spender, value); 430 | allowance[msg.sender][spender] = value; 431 | emit Approval(msg.sender, spender, value); 432 | 433 | return IApprovalReceiver(spender).onTokenApproval(msg.sender, value, data); 434 | } 435 | 436 | /// @dev Sets `value` as allowance of `spender` account over `owner` account's AnyswapV3ERC20 token, given `owner` account's signed approval. 437 | /// Emits {Approval} event. 438 | /// Requirements: 439 | /// - `deadline` must be timestamp in future. 440 | /// - `v`, `r` and `s` must be valid `secp256k1` signature from `owner` account over EIP712-formatted function arguments. 441 | /// - the signature must use `owner` account's current nonce (see {nonces}). 442 | /// - the signer cannot be zero address and must be `owner` account. 443 | /// For more information on signature format, see https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. 444 | /// AnyswapV3ERC20 token implementation adapted from https://github.com/albertocuestacanada/ERC20Permit/blob/master/contracts/ERC20Permit.sol. 445 | function permit(address target, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external override { 446 | require(block.timestamp <= deadline, "AnyswapV3ERC20: Expired permit"); 447 | 448 | bytes32 hashStruct = keccak256( 449 | abi.encode( 450 | PERMIT_TYPEHASH, 451 | target, 452 | spender, 453 | value, 454 | nonces[target]++, 455 | deadline)); 456 | 457 | require(verifyEIP712(target, hashStruct, v, r, s) || verifyPersonalSign(target, hashStruct, v, r, s)); 458 | 459 | // _approve(owner, spender, value); 460 | allowance[target][spender] = value; 461 | emit Approval(target, spender, value); 462 | } 463 | 464 | function transferWithPermit(address target, address to, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external override returns (bool) { 465 | require(block.timestamp <= deadline, "AnyswapV3ERC20: Expired permit"); 466 | 467 | bytes32 hashStruct = keccak256( 468 | abi.encode( 469 | TRANSFER_TYPEHASH, 470 | target, 471 | to, 472 | value, 473 | nonces[target]++, 474 | deadline)); 475 | 476 | require(verifyEIP712(target, hashStruct, v, r, s) || verifyPersonalSign(target, hashStruct, v, r, s)); 477 | 478 | require(to != address(0) || to != address(this)); 479 | 480 | uint256 balance = balanceOf[target]; 481 | require(balance >= value, "AnyswapV3ERC20: transfer amount exceeds balance"); 482 | 483 | balanceOf[target] = balance - value; 484 | balanceOf[to] += value; 485 | emit Transfer(target, to, value); 486 | 487 | return true; 488 | } 489 | 490 | function verifyEIP712(address target, bytes32 hashStruct, uint8 v, bytes32 r, bytes32 s) internal view returns (bool) { 491 | bytes32 hash = keccak256( 492 | abi.encodePacked( 493 | "\x19\x01", 494 | DOMAIN_SEPARATOR, 495 | hashStruct)); 496 | address signer = ecrecover(hash, v, r, s); 497 | return (signer != address(0) && signer == target); 498 | } 499 | 500 | function verifyPersonalSign(address target, bytes32 hashStruct, uint8 v, bytes32 r, bytes32 s) internal pure returns (bool) { 501 | bytes32 hash = prefixed(hashStruct); 502 | address signer = ecrecover(hash, v, r, s); 503 | return (signer != address(0) && signer == target); 504 | } 505 | 506 | // Builds a prefixed hash to mimic the behavior of eth_sign. 507 | function prefixed(bytes32 hash) internal pure returns (bytes32) { 508 | return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); 509 | } 510 | 511 | /// @dev Moves `value` AnyswapV3ERC20 token from caller's account to account (`to`). 512 | /// A transfer to `address(0)` triggers an ETH withdraw matching the sent AnyswapV3ERC20 token in favor of caller. 513 | /// Emits {Transfer} event. 514 | /// Returns boolean value indicating whether operation succeeded. 515 | /// Requirements: 516 | /// - caller account must have at least `value` AnyswapV3ERC20 token. 517 | function transfer(address to, uint256 value) external override returns (bool) { 518 | require(to != address(0) || to != address(this)); 519 | uint256 balance = balanceOf[msg.sender]; 520 | require(balance >= value, "AnyswapV3ERC20: transfer amount exceeds balance"); 521 | 522 | balanceOf[msg.sender] = balance - value; 523 | balanceOf[to] += value; 524 | emit Transfer(msg.sender, to, value); 525 | 526 | return true; 527 | } 528 | 529 | /// @dev Moves `value` AnyswapV3ERC20 token from account (`from`) to account (`to`) using allowance mechanism. 530 | /// `value` is then deducted from caller account's allowance, unless set to `type(uint256).max`. 531 | /// A transfer to `address(0)` triggers an ETH withdraw matching the sent AnyswapV3ERC20 token in favor of caller. 532 | /// Emits {Approval} event to reflect reduced allowance `value` for caller account to spend from account (`from`), 533 | /// unless allowance is set to `type(uint256).max` 534 | /// Emits {Transfer} event. 535 | /// Returns boolean value indicating whether operation succeeded. 536 | /// Requirements: 537 | /// - `from` account must have at least `value` balance of AnyswapV3ERC20 token. 538 | /// - `from` account must have approved caller to spend at least `value` of AnyswapV3ERC20 token, unless `from` and caller are the same account. 539 | function transferFrom(address from, address to, uint256 value) external override returns (bool) { 540 | require(to != address(0) || to != address(this)); 541 | if (from != msg.sender) { 542 | // _decreaseAllowance(from, msg.sender, value); 543 | uint256 allowed = allowance[from][msg.sender]; 544 | if (allowed != type(uint256).max) { 545 | require(allowed >= value, "AnyswapV3ERC20: request exceeds allowance"); 546 | uint256 reduced = allowed - value; 547 | allowance[from][msg.sender] = reduced; 548 | emit Approval(from, msg.sender, reduced); 549 | } 550 | } 551 | 552 | uint256 balance = balanceOf[from]; 553 | require(balance >= value, "AnyswapV3ERC20: transfer amount exceeds balance"); 554 | 555 | balanceOf[from] = balance - value; 556 | balanceOf[to] += value; 557 | emit Transfer(from, to, value); 558 | 559 | return true; 560 | } 561 | 562 | /// @dev Moves `value` AnyswapV3ERC20 token from caller's account to account (`to`), 563 | /// after which a call is executed to an ERC677-compliant contract with the `data` parameter. 564 | /// A transfer to `address(0)` triggers an ETH withdraw matching the sent AnyswapV3ERC20 token in favor of caller. 565 | /// Emits {Transfer} event. 566 | /// Returns boolean value indicating whether operation succeeded. 567 | /// Requirements: 568 | /// - caller account must have at least `value` AnyswapV3ERC20 token. 569 | /// For more information on transferAndCall format, see https://github.com/ethereum/EIPs/issues/677. 570 | function transferAndCall(address to, uint value, bytes calldata data) external override returns (bool) { 571 | require(to != address(0) || to != address(this)); 572 | 573 | uint256 balance = balanceOf[msg.sender]; 574 | require(balance >= value, "AnyswapV3ERC20: transfer amount exceeds balance"); 575 | 576 | balanceOf[msg.sender] = balance - value; 577 | balanceOf[to] += value; 578 | emit Transfer(msg.sender, to, value); 579 | 580 | return ITransferReceiver(to).onTokenTransfer(msg.sender, value, data); 581 | } 582 | } 583 | --------------------------------------------------------------------------------