FiatTokenV1

Description:

Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/upgradeability/draft-IERC1822.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
// OpenZeppelin Contracts v4.x.0 (proxy/ERC1822/IProxiable.sol)\r
\r
pragma solidity 0.8.11;\r
\r
/**\r
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\r
 * proxy whose upgrades are fully controlled by the current implementation.\r
 */\r
interface IERC1822Proxiable {\r
    /**\r
     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\r
     * address.\r
     *\r
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\r
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\r
     * function revert if invoked through a proxy.\r
     */\r
    function proxiableUUID() external view returns (bytes32);\r
}"
    },
    "contracts/upgradeability/ERC1967Upgrade.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Upgrade.sol)\r
\r
pragma solidity 0.8.11;\r
\r
import "./draft-IERC1822.sol";\r
import "../util/Address.sol";\r
import "../util/StorageSlot.sol";\r
\r
/**\r
 * @dev This abstract contract provides getters and event emitting update functions for\r
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\r
 *\r
 * _Available since v4.1._\r
 *\r
 * @custom:oz-upgrades-unsafe-allow delegatecall\r
 */\r
abstract contract ERC1967Upgrade {\r
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1\r
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\r
\r
    /**\r
     * @dev Storage slot with the address of the current implementation.\r
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is\r
     * validated in the constructor.\r
     */\r
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\r
\r
    /**\r
     * @dev Emitted when the implementation is upgraded.\r
     */\r
    event Upgraded(address indexed implementation);\r
\r
    /**\r
     * @dev Returns the current implementation address.\r
     */\r
    function _getImplementation() internal view returns (address) {\r
        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\r
    }\r
\r
    /**\r
     * @dev Stores a new address in the EIP1967 implementation slot.\r
     */\r
    function _setImplementation(address newImplementation) private {\r
        require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");\r
        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\r
    }\r
\r
    /**\r
     * @dev Perform implementation upgrade\r
     *\r
     * Emits an {Upgraded} event.\r
     */\r
    function _upgradeTo(address newImplementation) internal {\r
        _setImplementation(newImplementation);\r
        emit Upgraded(newImplementation);\r
    }\r
\r
    /**\r
     * @dev Perform implementation upgrade with additional setup call.\r
     *\r
     * Emits an {Upgraded} event.\r
     */\r
    function _upgradeToAndCall(\r
        address newImplementation,\r
        bytes memory data,\r
        bool forceCall\r
    ) internal {\r
        _upgradeTo(newImplementation);\r
        if (data.length > 0 || forceCall) {\r
            Address.functionDelegateCall(newImplementation, data);\r
        }\r
    }\r
\r
    /**\r
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\r
     *\r
     * Emits an {Upgraded} event.\r
     */\r
    function _upgradeToAndCallUUPS(\r
        address newImplementation,\r
        bytes memory data,\r
        bool forceCall\r
    ) internal {\r
        // Upgrades from old implementations will perform a rollback test. This test requires the new\r
        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\r
        // this special case will break upgrade paths from old UUPS implementation to new ones.\r
        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\r
            _setImplementation(newImplementation);\r
        } else {\r
            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\r
                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");\r
            } catch {\r
                revert("ERC1967Upgrade: new implementation is not UUPS");\r
            }\r
            _upgradeToAndCall(newImplementation, data, forceCall);\r
        }\r
    }\r
 \r
    uint256[50] private _gap;\r
}"
    },
    "contracts/upgradeability/UUPSUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/UUPSUpgradeable.sol)\r
\r
pragma solidity 0.8.11;\r
\r
import "./draft-IERC1822.sol";\r
import "./ERC1967Upgrade.sol";\r
\r
/**\r
 * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\r
 * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\r
 *\r
 * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\r
 * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\r
 * `UUPSUpgradeable` with a custom implementation of upgrades.\r
 *\r
 * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\r
 *\r
 * _Available since v4.1._\r
 */\r
abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {\r
    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\r
    address private immutable __self = address(this);\r
\r
    /**\r
     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\r
     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\r
     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\r
     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\r
     * fail.\r
     */\r
    modifier onlyProxy() {\r
        require(\r
            address(this) != __self,\r
            "Function must be called through delegatecall"\r
        );\r
        require(\r
            _getImplementation() == __self,\r
            "Function must be called through active proxy"\r
        );\r
        _;\r
    }\r
\r
    /**\r
     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\r
     * callable on the implementing contract but not through proxies.\r
     */\r
    modifier notDelegated() {\r
        require(\r
            address(this) == __self,\r
            "UUPSUpgradeable: must not be called through delegatecall"\r
        );\r
        _;\r
    }\r
\r
    /**\r
     * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\r
     * implementation. It is used to validate that the this implementation remains valid after an upgrade.\r
     *\r
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\r
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\r
     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\r
     */\r
    function proxiableUUID()\r
        external\r
        view\r
        virtual\r
        override\r
        notDelegated\r
        returns (bytes32)\r
    {\r
        return _IMPLEMENTATION_SLOT;\r
    }\r
\r
    /**\r
     * @dev Upgrade the implementation of the proxy to `newImplementation`.\r
     *\r
     * Calls {_authorizeUpgrade}.\r
     *\r
     * Emits an {Upgraded} event.\r
     */\r
    function upgradeTo(address newImplementation) external virtual onlyProxy {\r
        _authorizeUpgrade(newImplementation);\r
        _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\r
    }\r
\r
    /**\r
     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\r
     * encoded in `data`.\r
     *\r
     * Calls {_authorizeUpgrade}.\r
     *\r
     * Emits an {Upgraded} event.\r
     */\r
    function upgradeToAndCall(address newImplementation, bytes memory data)\r
        external\r
        payable\r
        virtual\r
        onlyProxy\r
    {\r
        _authorizeUpgrade(newImplementation);\r
        _upgradeToAndCallUUPS(newImplementation, data, true);\r
    }\r
\r
    /**\r
     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\r
     * {upgradeTo} and {upgradeToAndCall}.\r
     *\r
     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\r
     *\r
     * ```solidity\r
     * function _authorizeUpgrade(address) internal override onlyOwner {}\r
     * ```\r
     */\r
    function _authorizeUpgrade(address newImplementation) internal virtual;\r
\r
    uint256[50] private _gap;\r
}\r
"
    },
    "contracts/util/Address.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
// OpenZeppelin Contracts v4.4.0 (utils/Address.sol)\r
\r
pragma solidity 0.8.11;\r
\r
/**\r
 * @dev Collection of functions related to the address type\r
 */\r
library Address {\r
    /**\r
     * @dev Returns true if `account` is a contract.\r
     * @dev Forked from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4961a51cc736c7d4aa9bd2e11e4cbbaff73efee9/contracts/utils/Context.sol\r
     * Modifications:\r
     * 1. Change solidity version to 0.8.11\r
     *\r
     * [IMPORTANT]\r
     * ====\r
     * It is unsafe to assume that an address for which this function returns\r
     * false is an externally-owned account (EOA) and not a contract.\r
     *\r
     * Among others, `isContract` will return false for the following\r
     * types of addresses:\r
     *\r
     *  - an externally-owned account\r
     *  - a contract in construction\r
     *  - an address where a contract will be created\r
     *  - an address where a contract lived, but was destroyed\r
     * ====\r
     */\r
    function isContract(address account) internal view returns (bool) {\r
        // This method relies on extcodesize, which returns 0 for contracts in\r
        // construction, since the code is only stored at the end of the\r
        // constructor execution.\r
\r
        uint256 size;\r
        assembly {\r
            size := extcodesize(account)\r
        }\r
        return size > 0;\r
    }\r
\r
    /**\r
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\r
     * `recipient`, forwarding all available gas and reverting on errors.\r
     *\r
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\r
     * of certain opcodes, possibly making contracts go over the 2300 gas limit\r
     * imposed by `transfer`, making them unable to receive funds via\r
     * `transfer`. {sendValue} removes this limitation.\r
     *\r
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\r
     *\r
     * IMPORTANT: because control is transferred to `recipient`, care must be\r
     * taken to not create reentrancy vulnerabilities. Consider using\r
     * {ReentrancyGuard} or the\r
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\r
     */\r
    function sendValue(address payable recipient, uint256 amount) internal {\r
        require(address(this).balance >= amount, "Address: insufficient balance");\r
\r
        (bool success, ) = recipient.call{value: amount}("");\r
        require(success, "Address: unable to send value, recipient may have reverted");\r
    }\r
\r
    /**\r
     * @dev Performs a Solidity function call using a low level `call`. A\r
     * plain `call` is an unsafe replacement for a function call: use this\r
     * function instead.\r
     *\r
     * If `target` reverts with a revert reason, it is bubbled up by this\r
     * function (like regular Solidity function calls).\r
     *\r
     * Returns the raw returned data. To convert to the expected return value,\r
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\r
     *\r
     * Requirements:\r
     *\r
     * - `target` must be a contract.\r
     * - calling `target` with `data` must not revert.\r
     *\r
     * _Available since v3.1._\r
     */\r
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\r
        return functionCall(target, data, "Address: low-level call failed");\r
    }\r
\r
    /**\r
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\r
     * `errorMessage` as a fallback revert reason when `target` reverts.\r
     *\r
     * _Available since v3.1._\r
     */\r
    function functionCall(\r
        address target,\r
        bytes memory data,\r
        string memory errorMessage\r
    ) internal returns (bytes memory) {\r
        return functionCallWithValue(target, data, 0, errorMessage);\r
    }\r
\r
    /**\r
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r
     * but also transferring `value` wei to `target`.\r
     *\r
     * Requirements:\r
     *\r
     * - the calling contract must have an ETH balance of at least `value`.\r
     * - the called Solidity function must be `payable`.\r
     *\r
     * _Available since v3.1._\r
     */\r
    function functionCallWithValue(\r
        address target,\r
        bytes memory data,\r
        uint256 value\r
    ) internal returns (bytes memory) {\r
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");\r
    }\r
\r
    /**\r
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\r
     * with `errorMessage` as a fallback revert reason when `target` reverts.\r
     *\r
     * _Available since v3.1._\r
     */\r
    function functionCallWithValue(\r
        address target,\r
        bytes memory data,\r
        uint256 value,\r
        string memory errorMessage\r
    ) internal returns (bytes memory) {\r
        require(address(this).balance >= value, "Address: insufficient balance for call");\r
        require(isContract(target), "Address: call to non-contract");\r
\r
        (bool success, bytes memory returndata) = target.call{value: value}(data);\r
        return verifyCallResult(success, returndata, errorMessage);\r
    }\r
\r
    /**\r
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r
     * but performing a static call.\r
     *\r
     * _Available since v3.3._\r
     */\r
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\r
        return functionStaticCall(target, data, "Address: low-level static call failed");\r
    }\r
\r
    /**\r
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r
     * but performing a static call.\r
     *\r
     * _Available since v3.3._\r
     */\r
    function functionStaticCall(\r
        address target,\r
        bytes memory data,\r
        string memory errorMessage\r
    ) internal view returns (bytes memory) {\r
        require(isContract(target), "Address: static call to non-contract");\r
\r
        (bool success, bytes memory returndata) = target.staticcall(data);\r
        return verifyCallResult(success, returndata, errorMessage);\r
    }\r
\r
    /**\r
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r
     * but performing a delegate call.\r
     *\r
     * _Available since v3.4._\r
     */\r
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\r
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");\r
    }\r
\r
    /**\r
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r
     * but performing a delegate call.\r
     *\r
     * _Available since v3.4._\r
     */\r
    function functionDelegateCall(\r
        address target,\r
        bytes memory data,\r
        string memory errorMessage\r
    ) internal returns (bytes memory) {\r
        require(isContract(target), "Address: delegate call to non-contract");\r
\r
        (bool success, bytes memory returndata) = target.delegatecall(data);\r
        return verifyCallResult(success, returndata, errorMessage);\r
    }\r
\r
    /**\r
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\r
     * revert reason using the provided one.\r
     *\r
     * _Available since v4.3._\r
     */\r
    function verifyCallResult(\r
        bool success,\r
        bytes memory returndata,\r
        string memory errorMessage\r
    ) internal pure returns (bytes memory) {\r
        if (success) {\r
            return returndata;\r
        } else {\r
            // Look for revert reason and bubble it up if present\r
            if (returndata.length > 0) {\r
                // The easiest way to bubble the revert reason is using memory via assembly\r
\r
                assembly {\r
                    let returndata_size := mload(returndata)\r
                    revert(add(32, returndata), returndata_size)\r
                }\r
            } else {\r
                revert(errorMessage);\r
            }\r
        }\r
    }\r
}"
    },
    "contracts/util/ECRecover.sol": {
      "content": "/**\r
 * SPDX-License-Identifier: MIT\r
 *\r
 * Copyright (c) 2016-2019 zOS Global Limited\r
 * Copyright (c) 2018-2020 CENTRE SECZ\r
 *\r
 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
 * of this software and associated documentation files (the "Software"), to deal\r
 * in the Software without restriction, including without limitation the rights\r
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
 * copies of the Software, and to permit persons to whom the Software is\r
 * furnished to do so, subject to the following conditions:\r
 *\r
 * The above copyright notice and this permission notice shall be included in\r
 * copies or substantial portions of the Software.\r
 *\r
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
 * SOFTWARE.\r
 */\r
\r
pragma solidity 0.8.11;\r
\r
/**\r
 * @dev Forked from https://github.com/centrehq/centre-tokens/blob/37039f00534d3e5148269adf98bd2d42ea9fcfd7/contracts/util/ECRecover.sol\r
 * Modifications:\r
 * 1. Change solidity version to 0.8.11\r
 */\r
/**\r
 * @title ECRecover\r
 * @notice A library that provides a safe ECDSA recovery function\r
 */\r
library ECRecover {\r
    /**\r
     * @notice Recover signer's address from a signed message\r
     * @dev Adapted from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/65e4ffde586ec89af3b7e9140bdc9235d1254853/contracts/cryptography/ECDSA.sol\r
     * Modifications: Accept v, r, and s as separate arguments\r
     * @param digest    Keccak-256 hash digest of the signed message\r
     * @param v         v of the signature\r
     * @param r         r of the signature\r
     * @param s         s of the signature\r
     * @return Signer address\r
     */\r
    function recover(\r
        bytes32 digest,\r
        uint8 v,\r
        bytes32 r,\r
        bytes32 s\r
    ) internal pure returns (address) {\r
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\r
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\r
        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\r
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\r
        //\r
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\r
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\r
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\r
        // these malleable signatures as well.\r
        if (\r
            uint256(s) >\r
            0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0\r
        ) {\r
            revert("ECRecover: invalid signature 's' value");\r
        }\r
\r
        if (v != 27 && v != 28) {\r
            revert("ECRecover: invalid signature 'v' value");\r
        }\r
\r
        // If the signature is valid (and not malleable), return the signer address\r
        address signer = ecrecover(digest, v, r, s);\r
        require(signer != address(0), "ECRecover: invalid signature");\r
\r
        return signer;\r
    }\r
}"
    },
    "contracts/util/EIP712.sol": {
      "content": "/**\r
 * SPDX-License-Identifier: MIT\r
 *\r
 * Copyright (c) 2018-2020 CENTRE SECZ\r
 *\r
 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
 * of this software and associated documentation files (the "Software"), to deal\r
 * in the Software without restriction, including without limitation the rights\r
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
 * copies of the Software, and to permit persons to whom the Software is\r
 * furnished to do so, subject to the following conditions:\r
 *\r
 * The above copyright notice and this permission notice shall be included in\r
 * copies or substantial portions of the Software.\r
 *\r
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
 * SOFTWARE.\r
 */\r
\r
pragma solidity 0.8.11;\r
\r
import "./ECRecover.sol";\r
\r
/**\r
 * @title EIP712\r
 * @notice A library that provides EIP712 helper functions\r
 */\r
library EIP712 {\r
    /**\r
     * @notice Make EIP712 domain separator\r
     * @param name      Contract name\r
     * @param version   Contract version\r
     * @return Domain separator\r
     */\r
    function makeDomainSeparator(string memory name, string memory version)\r
        internal\r
        view\r
        returns (bytes32)\r
    {\r
        uint256 chainId;\r
        assembly {\r
            chainId := chainid()\r
        }\r
        return\r
            keccak256(\r
                abi.encode(\r
                    // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")\r
                    0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f,\r
                    keccak256(bytes(name)),\r
                    keccak256(bytes(version)),\r
                    chainId,\r
                    address(this)\r
                )\r
            );\r
    }\r
\r
    /**\r
     * @notice Recover signer's address from a EIP712 signature\r
     * @param domainSeparator   Domain separator\r
     * @param v                 v of the signature\r
     * @param r                 r of the signature\r
     * @param s                 s of the signature\r
     * @param typeHashAndData   Type hash concatenated with data\r
     * @return Signer's address\r
     */\r
    function recover(\r
        bytes32 domainSeparator,\r
        uint8 v,\r
        bytes32 r,\r
        bytes32 s,\r
        bytes memory typeHashAndData\r
    ) internal pure returns (address) {\r
        bytes32 digest = keccak256(\r
            abi.encodePacked(\r
                "\x19\x01",\r
                domainSeparator,\r
                keccak256(typeHashAndData)\r
            )\r
        );\r
        return ECRecover.recover(digest, v, r, s);\r
    }\r
}"
    },
    "contracts/util/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
// OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol)\r
\r
pragma solidity 0.8.11;\r
\r
/**\r
 * @dev Forked from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4961a51cc736c7d4aa9bd2e11e4cbbaff73efee9/contracts/token/ERC20/IERC20.sol\r
 * Modifications:\r
 * 1. Change solidity version to 0.8.11\r
 */\r
/**\r
 * @dev Interface of the ERC20 standard as defined in the EIP.\r
 */\r
interface IERC20 {\r
    /**\r
     * @dev Returns the amount of tokens in existence.\r
     */\r
    function totalSupply() external view returns (uint256);\r
\r
    /**\r
     * @dev Returns the amount of tokens owned by `account`.\r
     */\r
    function balanceOf(address account) external view returns (uint256);\r
\r
    /**\r
     * @dev Moves `amount` tokens from the caller's account to `recipient`.\r
     *\r
     * Returns a boolean value indicating whether the operation succeeded.\r
     *\r
     * Emits a {Transfer} event.\r
     */\r
    function transfer(address recipient, uint256 amount) external returns (bool);\r
\r
    /**\r
     * @dev Returns the remaining number of tokens that `spender` will be\r
     * allowed to spend on behalf of `owner` through {transferFrom}. This is\r
     * zero by default.\r
     *\r
     * This value changes when {approve} or {transferFrom} are called.\r
     */\r
    function allowance(address owner, address spender) external view returns (uint256);\r
\r
    /**\r
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\r
     *\r
     * Returns a boolean value indicating whether the operation succeeded.\r
     *\r
     * IMPORTANT: Beware that changing an allowance with this method brings the risk\r
     * that someone may use both the old and the new allowance by unfortunate\r
     * transaction ordering. One possible solution to mitigate this race\r
     * condition is to first reduce the spender's allowance to 0 and set the\r
     * desired value afterwards:\r
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\r
     *\r
     * Emits an {Approval} event.\r
     */\r
    function approve(address spender, uint256 amount) external returns (bool);\r
\r
    /**\r
     * @dev Moves `amount` tokens from `sender` to `recipient` using the\r
     * allowance mechanism. `amount` is then deducted from the caller's\r
     * allowance.\r
     *\r
     * Returns a boolean value indicating whether the operation succeeded.\r
     *\r
     * Emits a {Transfer} event.\r
     */\r
    function transferFrom(\r
        address sender,\r
        address recipient,\r
        uint256 amount\r
    ) external returns (bool);\r
\r
    /**\r
     * @dev Emitted when `value` tokens are moved from one account (`from`) to\r
     * another (`to`).\r
     *\r
     * Note that `value` may be zero.\r
     */\r
    event Transfer(address indexed from, address indexed to, uint256 value);\r
\r
    /**\r
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\r
     * a call to {approve}. `value` is the new allowance.\r
     */\r
    event Approval(address indexed owner, address indexed spender, uint256 value);\r
}"
    },
    "contracts/util/StorageSlot.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
\r
pragma solidity 0.8.11;\r
\r
/**\r
 * @dev Forked from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4961a51cc736c7d4aa9bd2e11e4cbbaff73efee9/contracts/utils/StorageSlot.sol\r
 * Modifications:\r
 * 1. Change solidity version to 0.8.11\r
 */\r
/**\r
 * @dev Library for reading and writing primitive types to specific storage slots.\r
 *\r
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\r
 * This library helps with reading and writing to such slots without the need for inline assembly.\r
 *\r
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\r
 *\r
 * Example usage to set ERC1967 implementation slot:\r
 * ```\r
 * contract ERC1967 {\r
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\r
 *\r
 *     function _getImplementation() internal view returns (address) {\r
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\r
 *     }\r
 *\r
 *     function _setImplementation(address newImplementation) internal {\r
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");\r
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\r
 *     }\r
 * }\r
 * ```\r
 *\r
 * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\r
 */\r
library StorageSlot {\r
    struct AddressSlot {\r
        address value;\r
    }\r
\r
    struct BooleanSlot {\r
        bool value;\r
    }\r
\r
    struct Bytes32Slot {\r
        bytes32 value;\r
    }\r
\r
    struct Uint256Slot {\r
        uint256 value;\r
    }\r
\r
    /**\r
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\r
     */\r
    function getAddressSlot(bytes32 slot)\r
        internal\r
        pure\r
        returns (AddressSlot storage r)\r
    {\r
        assembly {\r
            r.slot := slot\r
        }\r
    }\r
\r
    /**\r
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\r
     */\r
    function getBooleanSlot(bytes32 slot)\r
        internal\r
        pure\r
        returns (BooleanSlot storage r)\r
    {\r
        assembly {\r
            r.slot := slot\r
        }\r
    }\r
\r
    /**\r
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\r
     */\r
    function getBytes32Slot(bytes32 slot)\r
        internal\r
        pure\r
        returns (Bytes32Slot storage r)\r
    {\r
        assembly {\r
            r.slot := slot\r
        }\r
    }\r
\r
    /**\r
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\r
     */\r
    function getUint256Slot(bytes32 slot)\r
        internal\r
        pure\r
        returns (Uint256Slot storage r)\r
    {\r
        assembly {\r
            r.slot := slot\r
        }\r
    }\r
}\r
"
    },
    "contracts/v1/AbstractFiatTokenV1.sol": {
      "content": "/**\r
 * SPDX-License-Identifier: MIT\r
 *\r
 * Copyright (c) 2018-2020 CENTRE SECZ\r
 * Copyright (c) 2022 JPYC\r
 *\r
 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
 * of this software and associated documentation files (the "Software"), to deal\r
 * in the Software without restriction, including without limitation the rights\r
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
 * copies of the Software, and to permit persons to whom the Software is\r
 * furnished to do so, subject to the following conditions:\r
 *\r
 * The above copyright notice and this permission notice shall be included in\r
 * copies or substantial portions of the Software.\r
 *\r
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
 * SOFTWARE.\r
 */\r
\r
pragma solidity 0.8.11;\r
\r
import "../util/IERC20.sol";\r
\r
/**\r
 * @notice base abstract contract to inherit IERC20\r
 * @dev Forked from https://github.com/centrehq/centre-tokens/blob/37039f00534d3e5148269adf98bd2d42ea9fcfd7/contracts/v1/AbstractFiatTokenV1.sol\r
 * Modifications:\r
 * 1. Change solidity version to 0.8.11\r
 * 2. Add gap\r
 * 3. Add functions: _increaseAllowance & _decreaseAllowance\r
 */\r
\r
abstract contract AbstractFiatTokenV1 is IERC20 {\r
    function _approve(\r
        address owner,\r
        address spender,\r
        uint256 value\r
    ) internal virtual;\r
\r
    function _transfer(\r
        address from,\r
        address to,\r
        uint256 value\r
    ) internal virtual;\r
\r
    function _increaseAllowance(\r
        address owner,\r
        address spender,\r
        uint256 increment\r
    ) internal virtual;\r
\r
    function _decreaseAllowance(\r
        address owner,\r
        address spender,\r
        uint256 decrement\r
    ) internal virtual;\r
\r
    uint256[50] private __gap;\r
}"
    },
    "contracts/v1/Blocklistable.sol": {
      "content": "/**\r
 * SPDX-License-Identifier: MIT\r
 *\r
 * Copyright (c) 2018-2020 CENTRE SECZ\r
 * Copyright (c) 2022 JPYC\r
 *\r
 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
 * of this software and associated documentation files (the "Software"), to deal\r
 * in the Software without restriction, including without limitation the rights\r
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
 * copies of the Software, and to permit persons to whom the Software is\r
 * furnished to do so, subject to the following conditions:\r
 *\r
 * The above copyright notice and this permission notice shall be included in\r
 * copies or substantial portions of the Software.\r
 *\r
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
 * SOFTWARE.\r
 */\r
\r
pragma solidity 0.8.11;\r
\r
import "./Ownable.sol";\r
\r
/**\r
 * @dev Forked from https://github.com/centrehq/centre-tokens/blob/37039f00534d3e5148269adf98bd2d42ea9fcfd7/contracts/v1/Blacklistable.sol\r
 * Modifications:\r
 * 1. Change solidity version to 0.8.11\r
 * 2. Change bool -> uint256 for gas optimization\r
 * 3. Change blacklist -> blocklist\r
 * 4. Add gap\r
 */\r
/**\r
 * @title Blocklistable Token\r
 * @dev Allows accounts to be blocklisted by a "blocklister" role\r
 */\r
contract Blocklistable is Ownable {\r
    address public blocklister;\r
    mapping(address => uint256) internal blocklisted;\r
\r
    event Blocklisted(address indexed _account);\r
    event UnBlocklisted(address indexed _account);\r
    event BlocklisterChanged(address indexed newBlocklister);\r
\r
    /**\r
     * @dev Throws if called by any account other than the blocklister\r
     */\r
    modifier onlyBlocklister() {\r
        require(\r
            msg.sender == blocklister,\r
            "Blocklistable: caller is not the blocklister"\r
        );\r
        _;\r
    }\r
\r
    /**\r
     * @dev Throws if argument account is blocklisted\r
     * @param _account The address to check\r
     */\r
    modifier notBlocklisted(address _account) {\r
        require(\r
            blocklisted[_account] == 0,\r
            "Blocklistable: account is blocklisted"\r
        );\r
        _;\r
    }\r
\r
    /**\r
     * @dev Checks if account is blocklisted\r
     * @param _account The address to check\r
     * @return True if account is blocklisted\r
     */\r
    function isBlocklisted(address _account) external view returns (bool) {\r
        return blocklisted[_account] == 1;\r
    }\r
\r
    /**\r
     * @dev Adds account to blocklist\r
     * @param _account The address to blocklist\r
     */\r
    function blocklist(address _account) external onlyBlocklister {\r
        blocklisted[_account] = 1;\r
        emit Blocklisted(_account);\r
    }\r
\r
    /**\r
     * @dev Removes account from blocklist\r
     * @param _account The address to remove from the blocklist\r
     */\r
    function unBlocklist(address _account) external onlyBlocklister {\r
        blocklisted[_account] = 0;\r
        emit UnBlocklisted(_account);\r
    }\r
\r
    function updateBlocklister(address _newBlocklister) external onlyOwner {\r
        require(\r
            _newBlocklister != address(0),\r
            "Blocklistable: new blocklister is the zero address"\r
        );\r
        blocklister = _newBlocklister;\r
        emit BlocklisterChanged(blocklister);\r
    }\r
\r
    uint256[50] private __gap;\r
}"
    },
    "contracts/v1/EIP2612.sol": {
      "content": "/**\r
 * SPDX-License-Identifier: MIT\r
 *\r
 * Copyright (c) 2018-2020 CENTRE SECZ\r
 * Copyright (c) 2022 JPYC\r
 *\r
 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
 * of this software and associated documentation files (the "Software"), to deal\r
 * in the Software without restriction, including without limitation the rights\r
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
 * copies of the Software, and to permit persons to whom the Software is\r
 * furnished to do so, subject to the following conditions:\r
 *\r
 * The above copyright notice and this permission notice shall be included in\r
 * copies or substantial portions of the Software.\r
 *\r
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
 * SOFTWARE.\r
 */\r
\r
pragma solidity 0.8.11;\r
\r
import "./AbstractFiatTokenV1.sol";\r
import "./EIP712Domain.sol";\r
import "../util/EIP712.sol";\r
\r
/**\r
 * @dev Forked from https://github.com/centrehq/centre-tokens/blob/37039f00534d3e5148269adf98bd2d42ea9fcfd7/contracts/v2/EIP2612.sol\r
 * Modifications:\r
 * 1. Change solidity version to 0.8.11\r
 * 2. Make domain separator dynamic by adding function: domainSeparatorV4\r
 * 3. Add gap\r
 * 4. Change now to block.timestamp\r
 */\r
\r
/**\r
 * @title EIP-2612\r
 * @notice Provide internal implementation for gas-abstracted approvals\r
 */\r
abstract contract EIP2612 is AbstractFiatTokenV1, EIP712Domain {\r
    // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")\r
    bytes32 public constant PERMIT_TYPEHASH =\r
        0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\r
\r
    mapping(address => uint256) private _permitNonces;\r
\r
    /**\r
     * @notice Nonces for permit\r
     * @param owner Token owner's address (Authorizer)\r
     * @return Next nonce\r
     */\r
    function nonces(address owner) external view returns (uint256) {\r
        return _permitNonces[owner];\r
    }\r
\r
    /**\r
     * @notice Verify a signed approval permit and execute if valid\r
     * @param owner     Token owner's address (Authorizer)\r
     * @param spender   Spender's address\r
     * @param value     Amount of allowance\r
     * @param deadline  The time at which this expires (unix time)\r
     * @param v         v of the signature\r
     * @param r         r of the signature\r
     * @param s         s of the signature\r
     */\r
    function _permit(\r
        address owner,\r
        address spender,\r
        uint256 value,\r
        uint256 deadline,\r
        uint8 v,\r
        bytes32 r,\r
        bytes32 s\r
    ) internal {\r
        require(deadline >= block.timestamp, "EIP2612: permit is expired");\r
\r
        bytes memory data = abi.encode(\r
            PERMIT_TYPEHASH,\r
            owner,\r
            spender,\r
            value,\r
            _permitNonces[owner]++,\r
            deadline\r
        );\r
        require(\r
            EIP712.recover(_domainSeparatorV4(), v, r, s, data) == owner,\r
            "EIP2612: invalid signature"\r
        );\r
\r
        _approve(owner, spender, value);\r
    }\r
\r
    uint256[50] private __gap;\r
}\r
"
    },
    "contracts/v1/EIP3009.sol": {
      "content": "/**\r
 * SPDX-License-Identifier: MIT\r
 *\r
 * Copyright (c) 2018-2020 CENTRE SECZ\r
 * Copyright (c) 2022 JPYC\r
 *\r
 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
 * of this software and associated documentation files (the "Software"), to deal\r
 * in the Software without restriction, including without limitation the rights\r
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
 * copies of the Software, and to permit persons to whom the Software is\r
 * furnished to do so, subject to the following conditions:\r
 *\r
 * The above copyright notice and this permission notice shall be included in\r
 * copies or substantial portions of the Software.\r
 *\r
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
 * SOFTWARE.\r
 */\r
\r
pragma solidity 0.8.11;\r
\r
import "./AbstractFiatTokenV1.sol";\r
import "./EIP712Domain.sol";\r
import "../util/EIP712.sol";\r
\r
/**\r
 * @dev Forked from https://github.com/centrehq/centre-tokens/blob/37039f00534d3e5148269adf98bd2d42ea9fcfd7/contracts/v2/EIP3009.sol\r
 * Modifications:\r
 * 1. Change solidity version to 0.8.11\r
 * 2. Make domain separator dynamic by adding function: domainSeparatorV4\r
 * 3. Change _authorizationStates to uint256 for gas optimization\r
 * 4. Change now to block.timestamp\r
 * 5. Add gap\r
 */\r
\r
/**\r
 * @title EIP-3009\r
 * @notice Provide internal implementation for gas-abstracted transfers\r
 * @dev Contracts that inherit from this must wrap these with publicly\r
 * accessible functions, optionally adding modifiers where necessary\r
 */\r
abstract contract EIP3009 is AbstractFiatTokenV1, EIP712Domain {\r
    // keccak256("TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)")\r
    bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH =\r
        0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267;\r
\r
    // keccak256("ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)")\r
    bytes32 public constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH =\r
        0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8;\r
\r
    // keccak256("CancelAuthorization(address authorizer,bytes32 nonce)")\r
    bytes32 public constant CANCEL_AUTHORIZATION_TYPEHASH =\r
        0x158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a1597429;\r
\r
    /**\r
     * @dev authorizer address => nonce => bool (true if nonce is used)\r
     */\r
    mapping(address => mapping(bytes32 => uint256)) private _authorizationStates;\r
\r
    event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce);\r
    event AuthorizationCanceled(\r
        address indexed authorizer,\r
        bytes32 indexed nonce\r
    );\r
\r
    /**\r
     * @notice Returns the state of an authorization\r
     * @dev Nonces are randomly generated 32-byte data unique to the\r
     * authorizer's address\r
     * @param authorizer    Authorizer's address\r
     * @param nonce         Nonce of the authorization\r
     * @return True if the nonce is used\r
     */\r
    function authorizationState(address authorizer, bytes32 nonce)\r
        external\r
        view\r
        returns (bool)\r
    {\r
        return _authorizationStates[authorizer][nonce] == 1;\r
    }\r
\r
    /**\r
     * @notice Execute a transfer with a signed authorization\r
     * @param from          Payer's address (Authorizer)\r
     * @param to            Payee's address\r
     * @param value         Amount to be transferred\r
     * @param validAfter    The time after which this is valid (unix time)\r
     * @param validBefore   The time before which this is valid (unix time)\r
     * @param nonce         Unique nonce\r
     * @param v             v of the signature\r
     * @param r             r of the signature\r
     * @param s             s of the signature\r
     */\r
    function _transferWithAuthorization(\r
        address from,\r
        address to,\r
        uint256 value,\r
        uint256 validAfter,\r
        uint256 validBefore,\r
        bytes32 nonce,\r
        uint8 v,\r
        bytes32 r,\r
        bytes32 s\r
    ) internal {\r
        _requireValidAuthorization(from, nonce, validAfter, validBefore);\r
\r
        bytes memory data = abi.encode(\r
            TRANSFER_WITH_AUTHORIZATION_TYPEHASH,\r
            from,\r
            to,\r
            value,\r
            validAfter,\r
            validBefore,\r
            nonce\r
        );\r
        require(\r
            EIP712.recover(_domainSeparatorV4(), v, r, s, data) == from,\r
            "EIP3009: invalid signature"\r
        );\r
\r
        _markAuthorizationAsUsed(from, nonce);\r
        _transfer(from, to, value);\r
    }\r
\r
    /**\r
     * @notice Receive a transfer with a signed authorization from the payer\r
     * @dev This has an additional check to ensure that the payee's address\r
     * matches the caller of this function to prevent front-running attacks.\r
     * @param from          Payer's address (Authorizer)\r
     * @param to            Payee's address\r
     * @param value         Amount to be transferred\r
     * @param validAfter    The time after which this is valid (unix time)\r
     * @param validBefore   The time before which this is valid (unix time)\r
     * @param nonce         Unique nonce\r
     * @param v             v of the signature\r
     * @param r             r of the signature\r
     * @param s             s of the signature\r
     */\r
    function _receiveWithAuthorization(\r
        address from,\r
        address to,\r
        uint256 value,\r
        uint256 validAfter,\r
        uint256 validBefore,\r
        bytes32 nonce,\r
        uint8 v,\r
        bytes32 r,\r
        bytes32 s\r
    ) internal {\r
        require(to == msg.sender, "EIP3009: caller must be the payee");\r
        _requireValidAuthorization(from, nonce, validAfter, validBefore);\r
\r
        bytes memory data = abi.encode(\r
            RECEIVE_WITH_AUTHORIZATION_TYPEHASH,\r
            from,\r
            to,\r
            value,\r
            validAfter,\r
            validBefore,\r
            nonce\r
        );\r
        require(\r
            EIP712.recover(_domainSeparatorV4(), v, r, s, data) == from,\r
            "EIP3009: invalid signature"\r
        );\r
\r
        _markAuthorizationAsUsed(from, nonce);\r
        _transfer(from, to, value);\r
    }\r
\r
    /**\r
     * @notice Attempt to cancel an authorization\r
     * @param authorizer    Authorizer's address\r
     * @param nonce         Nonce of the authorization\r
     * @param v             v of the signature\r
     * @param r             r of the signature\r
     * @param s             s of the signature\r
     */\r
    function _cancelAuthorization(\r
        address authorizer,\r
        bytes32 nonce,\r
        uint8 v,\r
        bytes32 r,\r
        bytes32 s\r
    ) internal {\r
        _requireUnusedAuthorization(authorizer, nonce);\r
\r
        bytes memory data = abi.encode(\r
            CANCEL_AUTHORIZATION_TYPEHASH,\r
            authorizer,\r
            nonce\r
        );\r
        require(\r
            EIP712.recover(_domainSeparatorV4(), v, r, s, data) == authorizer,\r
            "EIP3009: invalid signature"\r
        );\r
\r
        _authorizationStates[authorizer][nonce] = 1;\r
        emit AuthorizationCanceled(authorizer, nonce);\r
    }\r
\r
    /**\r
     * @notice Check that an authorization is unused\r
     * @param authorizer    Authorizer's address\r
     * @param nonce         Nonce of the authorization\r
     */\r
    function _requireUnusedAuthorization(address authorizer, bytes32 nonce)\r
        private\r
        view\r
    {\r
        require(\r
            _authorizationStates[authorizer][nonce] == 0,\r
            "EIP3009: authorization is used or canceled"\r
        );\r
    }\r
\r
    /**\r
     * @notice Check that authorization is valid\r
     * @param authorizer    Authorizer's address\r
     * @param nonce         Nonce of the authorization\r
     * @param validAfter    The time after which this is valid (unix time)\r
     * @param validBefore   The time before which this is valid (unix time)\r
     */\r
    function _requireValidAuthorization(\r
        address authorizer,\r
        bytes32 nonce,\r
        uint256 validAfter,\r
        uint256 validBefore\r
    ) private view {\r
        require(\r
            block.timestamp > validAfter,\r
            "EIP3009: authorization is not yet valid"\r
        );\r
        require(\r
            block.timestamp < validBefore,\r
            "EIP3009: authorization is expired"\r
        );\r
        _requireUnusedAuthorization(authorizer, nonce);\r
    }\r
\r
    /**\r
     * @notice Mark an authorization as used\r
     * @param authorizer    Authorizer's address\r
     * @param nonce         Nonce of the authorization\r
     */\r
    function _markAuthorizationAsUsed(address authorizer, bytes32 nonce)\r
        private\r
    {\r
        _authorizationStates[authorizer][nonce] = 1;\r
        emit AuthorizationUsed(authorizer, nonce);\r
    }\r
\r
    uint256[50] private __gap;\r
}\r
"
    },
    "contracts/v1/EIP712Domain.sol": {
      "content": "/**\r
 * SPDX-License-Identifier: MIT\r
 *\r
 * Copyright (c) 2018-2020 CENTRE SECZ\r
 *\r
 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
 * of this software and associated documentation files (the "Software"), to deal\r
 * in the Software without restriction, including without limitation the rights\r
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
 * copies of the Software, and to permit persons to whom the Software is\r
 * furnished to do so, subject to the following conditions:\r
 *\r
 * The above copyright notice and this permission notice shall be included in\r
 * copies or substantial portions of the Software.\r
 *\r
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
 * SOFTWARE.\r
 */\r
\r
pragma solidity 0.8.11;\r
\r
import "../util/EIP712.sol";\r
\r
/**\r
 * @dev Forked from https://github.com/centrehq/centre-tokens/blob/37039f00534d3e5148269adf98bd2d42ea9fcfd7/contracts/v2/EIP712Domain.sol\r
 * Modifications:\r
 * 1. Change solidity version to 0.8.11\r
 * 2. Add 4 new state variables: DOMAIN_SEPARATOR, CHAIN_ID, NAME, VERSION\r
 * 3. Add new function _domainSeparatorV4\r
 * 4. Add gap\r
 */\r
\r
/**\r
 * @title EIP712 Domain\r
 */\r
contract EIP712Domain {\r
    /**\r
     * @dev EIP712 Domain Separator\r
     */\r
    bytes32 internal DOMAIN_SEPARATOR;\r
    uint256 internal CHAIN_ID;\r
    string internal NAME;\r
    string internal VERSION;\r
\r
    /**\r
    * @dev Returns the domain separator for the current chain.\r
    */\r
    function _domainSeparatorV4() public view returns (bytes32) {\r
        if(block.chainid == CHAIN_ID) {\r
            return DOMAIN_SEPARATOR;\r
        } else {\r
            return EIP712.makeDomainSeparator(NAME, VERSION);\r
        }\r
    }\r
\r
    uint256[50] private __gap;\r
}"
    },
    "contracts/v1/FiatTokenV1.sol": {
      "content": "/**\r
 * SPDX-License-Identifier: MIT\r
 *\r
 * Copyright (c) 2018-2020 CENTRE SECZ\r
 * Copyright (c) 2022 JPYC\r
 *\r
 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
 * of this software and associated documentation files (the "Software"), to deal\r
 * in the Software without restriction, including without limitation the rights\r
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
 * copies of the Software, and to permit persons to whom the Software is\r
 * furnished to do so, subject to the following conditions:\r
 *\r
 * The above copyright notice and this permission notice shall be included in\r
 * copies or substantial portions of the Software.\r
 *\r
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
 * SOFTWARE.\r
 */\r
\r
pragma solidity 0.8.11;\r
\r
import "./Ownable.sol";\r
import "./Pausable.sol";\r
import "./Blocklistable.sol";\r
import "../util/EIP712.sol";\r
import "./Rescuable.sol";\r
import "./EIP3009.sol";\r
import "./EIP2612.sol";\r
import "../upgradeability/UUPSUpgradeable.sol";\r
\r
/**\r
 * @dev ERC20 Token backed by fiat reserves. Forked from\r
 * https://github.com/centrehq/centre-tokens/blob/37039f00534d3e5148269adf98bd2d42ea9fcfd7/contracts/v1/FiatTokenV1.sol,\r
 * https://github.com/centrehq/centre-tokens/blob/37039f00534d3e5148269adf98bd2d42ea9fcfd7/contracts/v1.1/FiatTokenV1_1.sol,\r
 * https://github.com/centrehq/centre-tokens/blob/37039f00534d3e5148269adf98bd2d42ea9fcfd7/contracts/v2/FiatTokenV2.sol,\r
 * https://github.com/centrehq/centre-tokens/blob/37039f00534d3e5148269adf98bd2d42ea9fcfd7/contracts/v2/FiatTokenV2_1.sol\r
 * Modifications:\r
 * 1. Change solidity version to 0.8.11\r
 * 2. Use cashe for gas optimization\r
 * 3. Let initialize function initialize a rescuer\r
 * 4. Change materMinter -> minterAdmin\r
 * 5. Use initializedVersion to manage the version\r
 * 6. Check if the approved amount is max amount for gas optimization\r
 */\r
\r
/**\r
 * @title FiatToken\r
 * @dev ERC20 Token backed by fiat reserves\r
 */\r
contract FiatTokenV1 is\r
    Ownable,\r
    Pausable,\r
    Blocklistable,\r
    Rescuable,\r
    EIP3009,\r
    EIP2612,\r
    UUPSUpgradeable\r
{\r
    string public name;\r
    string public symbol;\r
    string public currency;\r
    uint256 internal totalSupply_;\r
    address public minterAdmin;\r
    uint8 public decimals;\r
    uint8 internal initializedVersion;\r
\r
    mapping(address => uint256) internal balances;\r
    mapping(address => mapping(address => uint256)) internal allowed;\r
    mapping(address => bool) internal minters;\r
    mapping(address => uint256) internal minterAllowed;\r
\r
    event Mint(address indexed minter, address indexed to, uint256 amount);\r
    event Burn(address indexed burner, uint256 amount);\r
    event MinterConfigured(address indexed minter, uint256 minterAllowedAmount);\r
    event MinterRemoved(address indexed oldMinter);\r
    event MinterAdminChanged(address indexed newMinterAdmin);\r
\r
    function initialize(\r
        string memory tokenName,\r
        string memory tokenSymbol,\r
        string memory tokenCurrency,\r
        uint8 tokenDecimals,\r
        address newMinterAdmin,\r
        address newPauser,\r
        address newBlocklister,\r
        address newRescuer,\r
        address newOwner\r
    ) public {\r
        require(\r
            initializedVersion == 0,\r
            "FiatToken: contract is already initialized"\r
        );\r
        require(\r
            newMinterAdmin != address(0),\r
            "FiatToken: new minterAdmin is the zero address"\r
        );\r
        require(\r
            newPauser != address(0),\r
            "FiatToken: new pauser is the zero address"\r
        );\r
        require(\r
            newBlocklister != address(0),\r
            "FiatToken: new blocklister is the zero address"\r
        );\r
        require(\r
            newRescuer != address(0),\r
            "FiatToken: new rescuer is the zero address"\r
        );\r
        require(\r
            newOwner != address(0),\r
            "FiatToken: new owner is the zero address"\r
        );\r
\r
        name = tokenName;\r
        symbol = tokenSymbol;\r
        currency = tokenCurrency;\r
        decimals = tokenDecimals;\r
        minterAdmin = newMinterAdmin;\r
        pauser = newPauser;\r
        blocklister = newBlocklister;\r
        rescuer = newRescuer;\r
        _transferOwnership(newOwner);\r
        blocklisted[address(this)] = 1;\r
        DOMAIN_SEPARATOR = EIP712.makeDomainSeparator(tokenName, "1");\r
        CHAIN_ID = block.chainid;\r
        NAME = tokenName;\r
        VERSION = "1";\r
        initializedVersion = 1;\r
    }\r
\r
    /**\r
     * @dev Throws if called by any account other than a minter\r
     */\r
    modifier onlyMinters() {\r
        require(minters[msg.sender], "FiatToken: caller is not a minter");\r
        _;\r
    }\r
\r
    /**\r
     * @dev Function to mint tokens\r
     * @param _to The address that will receive the minted tokens.\r
     * @param _amount The amount of tokens to mint. Must be less than or equal\r
     * to the minterAllowance of the caller.\r
     * @return A boolean that indicates if the operation was successful.\r
     */\r
    function mint(address _to, uint256 _amount)\r
        external\r
        whenNotPaused\r
        onlyMinters\r
        notBlocklisted(msg.sender)\r
        notBlocklisted(_to)\r
        returns (bool)\r
    {\r
        require(_to != address(0), "FiatToken: mint to the zero address");\r
        require(_amount > 0, "FiatToken: mint amount not greater than 0");\r
\r
        uint256 mintingAllowedAmount = minterAllowed[msg.sender];\r
        require(\r
            _amount <= mintingAllowedAmount,\r
            "FiatToken: mint amount exceeds minterAllowance"\r
        );\r
\r
        totalSupply_ = totalSupply_ + _amount;\r
        balances[_to] = balances[_to] + _amount;\r
        minterAllowed[msg.sender] = mintingAllowedAmount - _amount;\r
        emit Mint(msg.sender, _to, _amount);\r
        emit Transfer(address(0), _to, _amount);\r
        return true;\r
    }\r
\r
    /**\r
     * @dev Throws if called by any account other than the minterAdmin\r
     */\r
    modifier onlyMinterAdmin() {\r
        require(\r
            msg.sender == minterAdmin,\r
            "FiatToken: caller is not the minterAdmin"\r
        );\r
        _;\r
    }\r
\r
    /**\r
     * @dev Get minter allowance for an account\r
     * @param minter The address of the minter\r
     * @return Allowance of the minter can mint\r
     */\r
    function minterAllowance(address minter) external view returns (uint256) {\r
        return minterAllowed[minter];\r
    }\r
\r
    /**\r
     * @dev Checks if account is a minter\r
     * @param account The address to check\r
     * @return True if account is a minter\r
     */\r
    function isMinter(address account) external view returns (bool) {\r
        return minters[account];\r
    }\r
\r
    /**\r
     * @notice Amount of remaining tokens spender is allowed to transfer on\r
     * behalf of the token owner\r
     * @param owner     Token owner's address\r
     * @param spender   Spender's address\r
     * @return Allowance amount\r
     */\r
    function allowance(address owner, address spender)\r
        external\r
        view\r
        override\r
        returns (uint256)\r
    {\r
        return allowed[owner][spender];\r
    }\r
\r
    /**\r
     * @dev Get totalSupply of token\r
     * @return TotalSupply\r
     */\r
    function totalSupply() external view override returns (uint256) {\r
        return totalSupply_;\r
    }\r
\r
    /**\r
     * @dev Get token balance of an account\r
     * @param account address The account\r
     * @return Balance amount of the account\r
     */\r
    function balanceOf(address account)\r
        external\r
        view\r
        override\r
        returns (uint256)\r
    {\r
        return balances[account];\r
    }\r
\r
    /**\r
     * @notice Set spender's allowance over the caller's tokens to be a given\r
     * value.\r
     * @param spender   Spender's address\r
     * @param value     Allowance amount\r
     * @return True if successful\r
     */\r
    function approve(address spender, uint256 value)\r
        external\r
        override\r
        whenNotPaused\r
        notBlocklisted(msg.sender)\r
        notBlocklisted(spender)\r
        returns (bool)\r
    {\r
        _approve(msg.sender, spender, value);\r
        return true;\r
    }\r
\r
    /**\r
     * @dev Internal function to set allowance\r
     * @param owner     Token owner's address\r
     * @param spender   Spender's address\r
     * @param value     Allowance amount\r
     */\r
    function _approve(\r
        address owner,\r
        address spender,\r
        uint256 value\r
    ) internal override {\r
        require(owner != address(0), "FiatToken: approve from the zero address");\r
        require(spender != address(0), "FiatToken: approve to the zero address");\r
        allowed[owner][spender] = value;\r
        emit Approval(owner, spender, value);\r
    }\r
\r
    /**\r
     * @notice Transfer tokens by spending allowance\r
     * @param from  Payer's address\r
     * @param to    Payee's address\r
     * @param value Transfer amount\r
     * @return True if successful\r
     */\r
    function transferFrom(\r
        address from,\r
        address to,\r
        uint256 value\r
    )\r
        external\r
        override\r
        whenNotPaused\r
        notBlocklisted(msg.

Tags:
ERC20, Proxy, Mintable, Burnable, Pausable, Upgradeable, Factory|addr:0x1d0d41ca8d87d833773bd09afebb5bedcfd6b90a|verified:true|block:23379858|tx:0xf72122fb6c83f39354dda6ddf7e0c436b6281c944abe56367768dfe23e4156ba|first_check:1758105954

Submitted on: 2025-09-17 12:45:56

Comments

Log in to comment.

No comments yet.