// Source: contracts/interchain-token/ERC20Permit.sol pragma solidity ^0.8.0; // SPDX-License-Identifier: MIT // File @axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol@v6.0.4 /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { error InvalidAccount(); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File contracts/interchain-token/ERC20.sol /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is IERC20 { mapping(address => uint256) public override balanceOf; mapping(address => mapping(address => uint256)) public override allowance; uint256 public override totalSupply; uint256 internal constant UINT256_MAX = type(uint256).max; /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) external virtual override returns (bool) { _transfer(msg.sender, recipient, amount); return true; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) external virtual override returns (bool) { _approve(msg.sender, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) external virtual override returns (bool) { uint256 _allowance = allowance[sender][msg.sender]; if (_allowance != UINT256_MAX) { _approve(sender, msg.sender, _allowance - amount); } _transfer(sender, recipient, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool) { _approve(msg.sender, spender, allowance[msg.sender][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool) { _approve(msg.sender, spender, allowance[msg.sender][spender] - subtractedValue); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { if (sender == address(0) || recipient == address(0)) revert InvalidAccount(); balanceOf[sender] -= amount; balanceOf[recipient] += amount; emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { if (account == address(0)) revert InvalidAccount(); totalSupply += amount; balanceOf[account] += amount; emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { if (account == address(0)) revert InvalidAccount(); balanceOf[account] -= amount; totalSupply -= amount; emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { if (owner == address(0) || spender == address(0)) revert InvalidAccount(); allowance[owner][spender] = amount; emit Approval(owner, spender, amount); } } // File @axelar-network/axelar-cgp-solidity/contracts/interfaces/IERC20Permit.sol@v6.4.0 interface IERC20Permit { function DOMAIN_SEPARATOR() external view returns (bytes32); function nonces(address account) external view returns (uint256); function permit(address issuer, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; } // File contracts/interchain-token/ERC20Permit.sol /** * @title ERC20Permit Contract * @dev Extension of ERC20 to include permit functionality (EIP-2612). * Allows for approval of ERC20 tokens by signature rather than transaction. */ abstract contract ERC20Permit is IERC20, IERC20Permit, ERC20 { error PermitExpired(); error InvalidS(); error InvalidV(); error InvalidSignature(); /** * @dev Represents hash of the EIP-712 Domain Separator. */ bytes32 public nameHash; string private constant EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA = '\x19\x01'; // keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)') bytes32 private constant DOMAIN_TYPE_SIGNATURE_HASH = bytes32(0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f); // keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)') bytes32 private constant PERMIT_SIGNATURE_HASH = bytes32(0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9); /** * @dev Mapping of nonces for each address. */ mapping(address => uint256) public nonces; /** * @notice Internal function to set the token name hash * @param name The token name */ function _setNameHash(string memory name) internal { nameHash = keccak256(bytes(name)); } /** * @notice Calculates the domain separator. * @dev This is not cached because chainid can change on chain forks. */ // solhint-disable func-name-mixedcase // slither-disable-next-line naming-convention function DOMAIN_SEPARATOR() public view returns (bytes32) { return keccak256(abi.encode(DOMAIN_TYPE_SIGNATURE_HASH, nameHash, keccak256(bytes('1')), block.chainid, address(this))); } // solhint-enable func-name-mixedcase /** * @notice Permit the designated spender to spend the holder's tokens * @dev The permit function is used to allow a holder to designate a spender * to spend tokens on their behalf via a signed message. * @param issuer The address of the token holder * @param spender The address of the designated spender * @param value The number of tokens to be spent * @param deadline The time at which the permission to spend expires * @param v The recovery id of the signature * @param r Half of the ECDSA signature pair * @param s Half of the ECDSA signature pair */ function permit(address issuer, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external { if (block.timestamp > deadline) revert PermitExpired(); if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) revert InvalidS(); if (v != 27 && v != 28) revert InvalidV(); bytes32 digest = keccak256( abi.encodePacked( EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA, DOMAIN_SEPARATOR(), keccak256(abi.encode(PERMIT_SIGNATURE_HASH, issuer, spender, value, nonces[issuer]++, deadline)) ) ); address recoveredAddress = ecrecover(digest, v, r, s); if (recoveredAddress != issuer) revert InvalidSignature(); // _approve will revert if issuer is address(0x0) _approve(issuer, spender, value); } }