creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized < type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/draft-IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n    using AddressUpgradeable for address;\n\n    function safeTransfer(\n        IERC20Upgradeable token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20Upgradeable token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20Upgradeable token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20Upgradeable token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20Upgradeable token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    function safePermit(\n        IERC20PermitUpgradeable token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * The default value of {decimals} is 18. To select a different value for\n     * {decimals} you should overload it.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the value {ERC20} uses, unless this function is\n     * overridden;\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) public virtual override returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, amount);\n        _transfer(from, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        uint256 currentAllowance = allowance(owner, spender);\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(owner, spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     */\n    function _transfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {\n        require(from != address(0), \"ERC20: transfer from the zero address\");\n        require(to != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, amount);\n\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n            // decrementing then incrementing.\n            _balances[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        _afterTokenTransfer(from, to, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        unchecked {\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n            _balances[account] += amount;\n        }\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\n            _totalSupply -= amount;\n        }\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(\n        address owner,\n        address spender,\n        uint256 amount\n    ) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n     *\n     * Does not update the allowance amount in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Might emit an {Approval} event.\n     */\n    function _spendAllowance(\n        address owner,\n        address spender,\n        uint256 amount\n    ) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n            unchecked {\n                _approve(owner, spender, currentAllowance - amount);\n            }\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      },
      "contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\n\npragma solidity ^0.8.20;\n\ninterface IBasePolygonZkEVMGlobalExitRoot {\n    /**\n     * @dev Thrown when the caller is not the allowed contracts\n     */\n    error OnlyAllowedContracts();\n\n    function updateExitRoot(bytes32 newRollupExitRoot) external;\n\n    function globalExitRootMap(\n        bytes32 globalExitRootNum\n    ) external returns (uint256);\n}\n"
      },
      "contracts/interfaces/IBridgeMessageReceiver.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Define interface for PolygonZkEVM Bridge message receiver\n */\ninterface IBridgeMessageReceiver {\n    function onMessageReceived(\n        address originAddress,\n        uint32 originNetwork,\n        bytes memory data\n    ) external payable;\n}\n"
      },
      "contracts/lib/EmergencyManager.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Contract helper responsible to manage the emergency state\n */\ncontract EmergencyManager {\n    /**\n     * @dev Thrown when emergency state is active, and the function requires otherwise\n     */\n    error OnlyNotEmergencyState();\n\n    /**\n     * @dev Thrown when emergency state is not active, and the function requires otherwise\n     */\n    error OnlyEmergencyState();\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     */\n    uint256[10] private _gap;\n\n    // Indicates whether the emergency state is active or not\n    bool public isEmergencyState;\n\n    /**\n     * @dev Emitted when emergency state is activated\n     */\n    event EmergencyStateActivated();\n\n    /**\n     * @dev Emitted when emergency state is deactivated\n     */\n    event EmergencyStateDeactivated();\n\n    /**\n     * @notice Only allows a function to be callable if emergency state is unactive\n     */\n    modifier ifNotEmergencyState() {\n        if (isEmergencyState) {\n            revert OnlyNotEmergencyState();\n        }\n        _;\n    }\n\n    /**\n     * @notice Only allows a function to be callable if emergency state is active\n     */\n    modifier ifEmergencyState() {\n        if (!isEmergencyState) {\n            revert OnlyEmergencyState();\n        }\n        _;\n    }\n\n    /**\n     * @notice Activate emergency state\n     */\n    function _activateEmergencyState() internal virtual ifNotEmergencyState {\n        isEmergencyState = true;\n        emit EmergencyStateActivated();\n    }\n\n    /**\n     * @notice Deactivate emergency state\n     */\n    function _deactivateEmergencyState() internal virtual ifEmergencyState {\n        isEmergencyState = false;\n        emit EmergencyStateDeactivated();\n    }\n}\n"
      },
      "contracts/lib/GlobalExitRootLib.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\n\npragma solidity 0.8.20;\n\n/**\n * @dev A library that provides the necessary calculations to calculate the global exit root\n */\nlibrary GlobalExitRootLib {\n    function calculateGlobalExitRoot(\n        bytes32 mainnetExitRoot,\n        bytes32 rollupExitRoot\n    ) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(mainnetExitRoot, rollupExitRoot));\n    }\n}\n"
      },
      "contracts/lib/TokenWrapped.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n// Implementation of permit based on https://github.com/WETH10/WETH10/blob/main/contracts/WETH10.sol\npragma solidity 0.8.20;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TokenWrapped is ERC20 {\n    // Domain typehash\n    bytes32 public constant DOMAIN_TYPEHASH =\n        keccak256(\n            \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n        );\n    // Permit typehash\n    bytes32 public constant PERMIT_TYPEHASH =\n        keccak256(\n            \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n        );\n\n    // Version\n    string public constant VERSION = \"1\";\n\n    // Chain id on deployment\n    uint256 public immutable deploymentChainId;\n\n    // Domain separator calculated on deployment\n    bytes32 private immutable _DEPLOYMENT_DOMAIN_SEPARATOR;\n\n    // PolygonZkEVM Bridge address\n    address public immutable bridgeAddress;\n\n    // Decimals\n    uint8 private immutable _decimals;\n\n    // Permit nonces\n    mapping(address => uint256) public nonces;\n\n    modifier onlyBridge() {\n        require(\n            msg.sender == bridgeAddress,\n            \"TokenWrapped::onlyBridge: Not PolygonZkEVMBridge\"\n        );\n        _;\n    }\n\n    constructor(\n        string memory name,\n        string memory symbol,\n        uint8 __decimals\n    ) ERC20(name, symbol) {\n        bridgeAddress = msg.sender;\n        _decimals = __decimals;\n        deploymentChainId = block.chainid;\n        _DEPLOYMENT_DOMAIN_SEPARATOR = _calculateDomainSeparator(block.chainid);\n    }\n\n    function mint(address to, uint256 value) external onlyBridge {\n        _mint(to, value);\n    }\n\n    // Notice that is not require to approve wrapped tokens to use the bridge\n    function burn(address account, uint256 value) external onlyBridge {\n        _burn(account, value);\n    }\n\n    function decimals() public view virtual override returns (uint8) {\n        return _decimals;\n    }\n\n    // Permit relative functions\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external {\n        require(\n            block.timestamp <= deadline,\n            \"TokenWrapped::permit: Expired permit\"\n        );\n\n        bytes32 hashStruct = keccak256(\n            abi.encode(\n                PERMIT_TYPEHASH,\n                owner,\n                spender,\n                value,\n                nonces[owner]++,\n                deadline\n            )\n        );\n\n        bytes32 digest = keccak256(\n            abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR(), hashStruct)\n        );\n\n        address signer = ecrecover(digest, v, r, s);\n        require(\n            signer != address(0) && signer == owner,\n            \"TokenWrapped::permit: Invalid signature\"\n        );\n\n        _approve(owner, spender, value);\n    }\n\n    /**\n     * @notice Calculate domain separator, given a chainID.\n     * @param chainId Current chainID\n     */\n    function _calculateDomainSeparator(\n        uint256 chainId\n    ) private view returns (bytes32) {\n        return\n            keccak256(\n                abi.encode(\n                    DOMAIN_TYPEHASH,\n                    keccak256(bytes(name())),\n                    keccak256(bytes(VERSION)),\n                    chainId,\n                    address(this)\n                )\n            );\n    }\n\n    /// @dev Return the DOMAIN_SEPARATOR.\n    function DOMAIN_SEPARATOR() public view returns (bytes32) {\n        return\n            block.chainid == deploymentChainId\n                ? _DEPLOYMENT_DOMAIN_SEPARATOR\n                : _calculateDomainSeparator(block.chainid);\n    }\n}\n"
      },
      "contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\n\npragma solidity ^0.8.20;\nimport \"../../interfaces/IBasePolygonZkEVMGlobalExitRoot.sol\";\n\ninterface IPolygonZkEVMBridgeV2 {\n    /**\n     * @dev Thrown when the destination network is invalid\n     */\n    error DestinationNetworkInvalid();\n\n    /**\n     * @dev Thrown when the amount does not match msg.value\n     */\n    error AmountDoesNotMatchMsgValue();\n\n    /**\n     * @dev Thrown when user is bridging tokens and is also sending a value\n     */\n    error MsgValueNotZero();\n\n    /**\n     * @dev Thrown when the Ether transfer on claimAsset fails\n     */\n    error EtherTransferFailed();\n\n    /**\n     * @dev Thrown when the message transaction on claimMessage fails\n     */\n    error MessageFailed();\n\n    /**\n     * @dev Thrown when the global exit root does not exist\n     */\n    error GlobalExitRootInvalid();\n\n    /**\n     * @dev Thrown when the smt proof does not match\n     */\n    error InvalidSmtProof();\n\n    /**\n     * @dev Thrown when an index is already claimed\n     */\n    error AlreadyClaimed();\n\n    /**\n     * @dev Thrown when the owner of permit does not match the sender\n     */\n    error NotValidOwner();\n\n    /**\n     * @dev Thrown when the spender of the permit does not match this contract address\n     */\n    error NotValidSpender();\n\n    /**\n     * @dev Thrown when the amount of the permit does not match\n     */\n    error NotValidAmount();\n\n    /**\n     * @dev Thrown when the permit data contains an invalid signature\n     */\n    error NotValidSignature();\n\n    /**\n     * @dev Thrown when sender is not the rollup manager\n     */\n    error OnlyRollupManager();\n\n    /**\n     * @dev Thrown when the permit data contains an invalid signature\n     */\n    error NativeTokenIsEther();\n\n    /**\n     * @dev Thrown when the permit data contains an invalid signature\n     */\n    error NoValueInMessagesOnGasTokenNetworks();\n\n    /**\n     * @dev Thrown when the permit data contains an invalid signature\n     */\n    error GasTokenNetworkMustBeZeroOnEther();\n\n    /**\n     * @dev Thrown when the wrapped token deployment fails\n     */\n    error FailedTokenWrappedDeployment();\n\n    function wrappedTokenToTokenInfo(\n        address destinationAddress\n    ) external view returns (uint32, address);\n\n    function updateGlobalExitRoot() external;\n\n    function activateEmergencyState() external;\n\n    function deactivateEmergencyState() external;\n\n    function bridgeAsset(\n        uint32 destinationNetwork,\n        address destinationAddress,\n        uint256 amount,\n        address token,\n        bool forceUpdateGlobalExitRoot,\n        bytes calldata permitData\n    ) external payable;\n\n    function bridgeMessage(\n        uint32 destinationNetwork,\n        address destinationAddress,\n        bool forceUpdateGlobalExitRoot,\n        bytes calldata metadata\n    ) external payable;\n\n    function bridgeMessageWETH(\n        uint32 destinationNetwork,\n        address destinationAddress,\n        uint256 amountWETH,\n        bool forceUpdateGlobalExitRoot,\n        bytes calldata metadata\n    ) external;\n\n    function claimAsset(\n        bytes32[32] calldata smtProofLocalExitRoot,\n        bytes32[32] calldata smtProofRollupExitRoot,\n        uint256 globalIndex,\n        bytes32 mainnetExitRoot,\n        bytes32 rollupExitRoot,\n        uint32 originNetwork,\n        address originTokenAddress,\n        uint32 destinationNetwork,\n        address destinationAddress,\n        uint256 amount,\n        bytes calldata metadata\n    ) external;\n\n    function claimMessage(\n        bytes32[32] calldata smtProofLocalExitRoot,\n        bytes32[32] calldata smtProofRollupExitRoot,\n        uint256 globalIndex,\n        bytes32 mainnetExitRoot,\n        bytes32 rollupExitRoot,\n        uint32 originNetwork,\n        address originAddress,\n        uint32 destinationNetwork,\n        address destinationAddress,\n        uint256 amount,\n        bytes calldata metadata\n    ) external;\n\n    function initialize(\n        uint32 _networkID,\n        address _gasTokenAddress,\n        uint32 _gasTokenNetwork,\n        IBasePolygonZkEVMGlobalExitRoot _globalExitRootManager,\n        address _polygonRollupManager,\n        bytes memory _gasTokenMetadata\n    ) external;\n\n    function getTokenMetadata(\n        address token\n    ) external view returns (bytes memory);\n}\n"
      },
      "contracts/v2/lib/DepositContractBase.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.20;\n\n/**\n * This contract will be used as a helper for all the sparse merkle tree related functions\n * Based on the implementation of the deposit eth2.0 contract https://github.com/ethereum/consensus-specs/blob/dev/solidity_deposit_contract/deposit_contract.sol\n */\ncontract DepositContractBase {\n    /**\n     * @dev Thrown when the merkle tree is full\n     */\n    error MerkleTreeFull();\n\n    // Merkle tree levels\n    uint256 internal constant _DEPOSIT_CONTRACT_TREE_DEPTH = 32;\n\n    // This ensures `depositCount` will fit into 32-bits\n    uint256 internal constant _MAX_DEPOSIT_COUNT =\n        2 ** _DEPOSIT_CONTRACT_TREE_DEPTH - 1;\n\n    // Branch array which contains the necessary sibilings to compute the next root when a new\n    // leaf is inserted\n    bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] internal _branch;\n\n    // Counter of current deposits\n    uint256 public depositCount;\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     */\n    uint256[10] private _gap;\n\n    /**\n     * @notice Computes and returns the merkle root\n     */\n    function getRoot() public view virtual returns (bytes32) {\n        bytes32 node;\n        uint256 size = depositCount;\n        bytes32 currentZeroHashHeight = 0;\n\n        for (\n            uint256 height = 0;\n            height < _DEPOSIT_CONTRACT_TREE_DEPTH;\n            height++\n        ) {\n            if (((size >> height) & 1) == 1)\n                node = keccak256(abi.encodePacked(_branch[height], node));\n            else\n                node = keccak256(abi.encodePacked(node, currentZeroHashHeight));\n\n            currentZeroHashHeight = keccak256(\n                abi.encodePacked(currentZeroHashHeight, currentZeroHashHeight)\n            );\n        }\n        return node;\n    }\n\n    /**\n     * @notice Add a new leaf to the merkle tree\n     * @param leaf Leaf\n     */\n    function _addLeaf(bytes32 leaf) internal {\n        bytes32 node = leaf;\n\n        // Avoid overflowing the Merkle tree (and prevent edge case in computing `_branch`)\n        if (depositCount >= _MAX_DEPOSIT_COUNT) {\n            revert MerkleTreeFull();\n        }\n\n        // Add deposit data root to Merkle tree (update a single `_branch` node)\n        uint256 size = ++depositCount;\n        for (\n            uint256 height = 0;\n            height < _DEPOSIT_CONTRACT_TREE_DEPTH;\n            height++\n        ) {\n            if (((size >> height) & 1) == 1) {\n                _branch[height] = node;\n                return;\n            }\n            node = keccak256(abi.encodePacked(_branch[height], node));\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Verify merkle proof\n     * @param leafHash Leaf hash\n     * @param smtProof Smt proof\n     * @param index Index of the leaf\n     * @param root Merkle root\n     */\n    function verifyMerkleProof(\n        bytes32 leafHash,\n        bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProof,\n        uint32 index,\n        bytes32 root\n    ) public pure returns (bool) {\n        return calculateRoot(leafHash, smtProof, index) == root;\n    }\n\n    /**\n     * @notice Calculate root from merkle proof\n     * @param leafHash Leaf hash\n     * @param smtProof Smt proof\n     * @param index Index of the leaf\n     */\n    function calculateRoot(\n        bytes32 leafHash,\n        bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProof,\n        uint32 index\n    ) public pure returns (bytes32) {\n        bytes32 node = leafHash;\n\n        // Compute root\n        for (\n            uint256 height = 0;\n            height < _DEPOSIT_CONTRACT_TREE_DEPTH;\n            height++\n        ) {\n            if (((index >> height) & 1) == 1)\n                node = keccak256(abi.encodePacked(smtProof[height], node));\n            else node = keccak256(abi.encodePacked(node, smtProof[height]));\n        }\n\n        return node;\n    }\n}\n"
      },
      "contracts/v2/lib/DepositContractV2.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.20;\n\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"./DepositContractBase.sol\";\n\n/**\n * This contract will be used in the PolygonZkEVMBridge contract, it inherits the DepositContractBase and adds the logic\n * to calculate the leaf of the tree\n */\ncontract DepositContractV2 is ReentrancyGuardUpgradeable, DepositContractBase {\n    /**\n     * @notice Given the leaf data returns the leaf value\n     * @param leafType Leaf type -->  [0] transfer Ether / ERC20 tokens, [1] message\n     * @param originNetwork Origin Network\n     * @param originAddress [0] Origin token address, 0 address is reserved for ether, [1] msg.sender of the message\n     * @param destinationNetwork Destination network\n     * @param destinationAddress Destination address\n     * @param amount [0] Amount of tokens/ether, [1] Amount of ether\n     * @param metadataHash Hash of the metadata\n     */\n    function getLeafValue(\n        uint8 leafType,\n        uint32 originNetwork,\n        address originAddress,\n        uint32 destinationNetwork,\n        address destinationAddress,\n        uint256 amount,\n        bytes32 metadataHash\n    ) public pure returns (bytes32) {\n        return\n            keccak256(\n                abi.encodePacked(\n                    leafType,\n                    originNetwork,\n                    originAddress,\n                    destinationNetwork,\n                    destinationAddress,\n                    amount,\n                    metadataHash\n                )\n            );\n    }\n}\n"
      },
      "contracts/v2/PolygonZkEVMBridgeV2.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\n\npragma solidity 0.8.20;\n\nimport \"./lib/DepositContractV2.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../lib/TokenWrapped.sol\";\nimport \"../interfaces/IBasePolygonZkEVMGlobalExitRoot.sol\";\nimport \"../interfaces/IBridgeMessageReceiver.sol\";\nimport \"./interfaces/IPolygonZkEVMBridgeV2.sol\";\nimport \"../lib/EmergencyManager.sol\";\nimport \"../lib/GlobalExitRootLib.sol\";\n\n/**\n * PolygonZkEVMBridge that will be deployed on Ethereum and all Polygon rollups\n * Contract responsible to manage the token interactions with other networks\n */\ncontract PolygonZkEVMBridgeV2 is\n    DepositContractV2,\n    EmergencyManager,\n    IPolygonZkEVMBridgeV2\n{\n    using SafeERC20Upgradeable for IERC20Upgradeable;\n\n    // Wrapped Token information struct\n    struct TokenInformation {\n        uint32 originNetwork;\n        address originTokenAddress;\n    }\n\n    // bytes4(keccak256(bytes(\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\")));\n    bytes4 private constant _PERMIT_SIGNATURE = 0xd505accf;\n\n    // bytes4(keccak256(bytes(\"permit(address,address,uint256,uint256,bool,uint8,bytes32,bytes32)\")));\n    bytes4 private constant _PERMIT_SIGNATURE_DAI = 0x8fcbaf0c;\n\n    // Mainnet identifier\n    uint32 private constant _MAINNET_NETWORK_ID = 0;\n\n    // ZkEVM identifier\n    uint32 private constant _ZKEVM_NETWORK_ID = 1;\n\n    // Leaf type asset\n    uint8 private constant _LEAF_TYPE_ASSET = 0;\n\n    // Leaf type message\n    uint8 private constant _LEAF_TYPE_MESSAGE = 1;\n\n    // Nullifier offset\n    uint256 private constant _MAX_LEAFS_PER_NETWORK = 2 ** 32;\n\n    // Indicate where's the mainnet flag bit in the global index\n    uint256 private constant _GLOBAL_INDEX_MAINNET_FLAG = 2 ** 64;\n\n    // Init code of the erc20 wrapped token, to deploy a wrapped token the constructor parameters must be appended\n    bytes public constant BASE_INIT_BYTECODE_WRAPPED_TOKEN =\n        hex\"6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033\";\n\n    // Network identifier\n    uint32 public networkID;\n\n    // Global Exit Root address\n    IBasePolygonZkEVMGlobalExitRoot public globalExitRootManager;\n\n    // Last updated deposit count to the global exit root manager\n    uint32 public lastUpdatedDepositCount;\n\n    // Leaf index --> claimed bit map\n    mapping(uint256 => uint256) public claimedBitMap;\n\n    // keccak256(OriginNetwork || tokenAddress) --> Wrapped token address\n    mapping(bytes32 => address) public tokenInfoToWrappedToken;\n\n    // Wrapped token Address --> Origin token information\n    mapping(address => TokenInformation) public wrappedTokenToTokenInfo;\n\n    // Rollup manager address, previously PolygonZkEVM\n    /// @custom:oz-renamed-from polygonZkEVMaddress\n    address public polygonRollupManager;\n\n    // Native address\n    address public gasTokenAddress;\n\n    // Native address\n    uint32 public gasTokenNetwork;\n\n    // Gas token metadata\n    bytes public gasTokenMetadata;\n\n    // WETH address\n    TokenWrapped public WETHToken;\n\n    /**\n     * @dev Emitted when bridge assets or messages to another network\n     */\n    event BridgeEvent(\n        uint8 leafType,\n        uint32 originNetwork,\n        address originAddress,\n        uint32 destinationNetwork,\n        address destinationAddress,\n        uint256 amount,\n        bytes metadata,\n        uint32 depositCount\n    );\n\n    /**\n     * @dev Emitted when a claim is done from another network\n     */\n    event ClaimEvent(\n        uint256 globalIndex,\n        uint32 originNetwork,\n        address originAddress,\n        address destinationAddress,\n        uint256 amount\n    );\n\n    /**\n     * @dev Emitted when a new wrapped token is created\n     */\n    event NewWrappedToken(\n        uint32 originNetwork,\n        address originTokenAddress,\n        address wrappedTokenAddress,\n        bytes metadata\n    );\n\n    /**\n     * Disable initalizers on the implementation following the best practices\n     */\n    constructor() {\n        _disableInitializers();\n    }\n\n    /**\n     * @param _networkID networkID\n     * @param _gasTokenAddress gas token address\n     * @param _gasTokenNetwork gas token network\n     * @param _globalExitRootManager global exit root manager address\n     * @param _polygonRollupManager polygonZkEVM address\n     * @notice The value of `_polygonRollupManager` on the L2 deployment of the contract will be address(0), so\n     * emergency state is not possible for the L2 deployment of the bridge, intentionally\n     * @param _gasTokenMetadata Abi encoded gas token metadata\n     */\n    function initialize(\n        uint32 _networkID,\n        address _gasTokenAddress,\n        uint32 _gasTokenNetwork,\n        IBasePolygonZkEVMGlobalExitRoot _globalExitRootManager,\n        address _polygonRollupManager,\n        bytes memory _gasTokenMetadata\n    ) external virtual initializer {\n        networkID = _networkID;\n        globalExitRootManager = _globalExitRootManager;\n        polygonRollupManager = _polygonRollupManager;\n\n        // Set gas token\n        if (_gasTokenAddress == address(0)) {\n            // Gas token will be ether\n            if (_gasTokenNetwork != 0) {\n                revert GasTokenNetworkMustBeZeroOnEther();\n            }\n            // WETHToken, gasTokenAddress and gasTokenNetwork will be 0\n            // gasTokenMetadata will be empty\n        } else {\n            // Gas token will be an erc20\n            gasTokenAddress = _gasTokenAddress;\n            gasTokenNetwork = _gasTokenNetwork;\n            gasTokenMetadata = _gasTokenMetadata;\n\n            // Create a wrapped token for WETH, with salt == 0\n            WETHToken = _deployWrappedToken(\n                0, // salt\n                abi.encode(\"Wrapped Ether\", \"WETH\", 18)\n            );\n        }\n\n        // Initialize OZ contracts\n        __ReentrancyGuard_init();\n    }\n\n    modifier onlyRollupManager() {\n        if (polygonRollupManager != msg.sender) {\n            revert OnlyRollupManager();\n        }\n        _;\n    }\n\n    /**\n     * @notice Deposit add a new leaf to the merkle tree\n     * note If this function is called with a reentrant token, it would be possible to `claimTokens` in the same call\n     * Reducing the supply of tokens on this contract, and actually locking tokens in the contract.\n     * Therefore we recommend to third parties bridges that if they do implement reentrant call of `beforeTransfer` of some reentrant tokens\n     * do not call any external address in that case\n     * note User/UI must be aware of the existing/available networks when choosing the destination network\n     * @param destinationNetwork Network destination\n     * @param destinationAddress Address destination\n     * @param amount Amount of tokens\n     * @param token Token address, 0 address is reserved for ether\n     * @param forceUpdateGlobalExitRoot Indicates if the new global exit root is updated or not\n     * @param permitData Raw data of the call `permit` of the token\n     */\n    function bridgeAsset(\n        uint32 destinationNetwork,\n        address destinationAddress,\n        uint256 amount,\n        address token,\n        bool forceUpdateGlobalExitRoot,\n        bytes calldata permitData\n    ) public payable virtual ifNotEmergencyState nonReentrant {\n        if (destinationNetwork == networkID) {\n            revert DestinationNetworkInvalid();\n        }\n\n        address originTokenAddress;\n        uint32 originNetwork;\n        bytes memory metadata;\n        uint256 leafAmount = amount;\n\n        if (token == address(0)) {\n            // Check gas token transfer\n            if (msg.value != amount) {\n                revert AmountDoesNotMatchMsgValue();\n            }\n\n            // Set gas token parameters\n            originNetwork = gasTokenNetwork;\n            originTokenAddress = gasTokenAddress;\n            metadata = gasTokenMetadata;\n        } else {\n            // Check msg.value is 0 if tokens are bridged\n            if (msg.value != 0) {\n                revert MsgValueNotZero();\n            }\n\n            // Check if it's WETH, this only applies on L2 networks with gasTokens\n            // In case ether is the native token, WETHToken will be 0, and the address 0 is already checked\n            if (token == address(WETHToken)) {\n                // Burn tokens\n                TokenWrapped(token).burn(msg.sender, amount);\n\n                // Both origin network and originTokenAddress will be 0\n                // Metadata will be empty\n            } else {\n                TokenInformation memory tokenInfo = wrappedTokenToTokenInfo[\n                    token\n                ];\n\n                if (tokenInfo.originTokenAddress != address(0)) {\n                    // The token is a wrapped token from another network\n\n                    // Burn tokens\n                    TokenWrapped(token).burn(msg.sender, amount);\n\n                    originTokenAddress = tokenInfo.originTokenAddress;\n                    originNetwork = tokenInfo.originNetwork;\n                } else {\n                    // Use permit if any\n                    if (permitData.length != 0) {\n                        _permit(token, amount, permitData);\n                    }\n\n                    // In order to support fee tokens check the amount received, not the transferred\n                    uint256 balanceBefore = IERC20Upgradeable(token).balanceOf(\n                        address(this)\n                    );\n                    IERC20Upgradeable(token).safeTransferFrom(\n                        msg.sender,\n                        address(this),\n                        amount\n                    );\n                    uint256 balanceAfter = IERC20Upgradeable(token).balanceOf(\n                        address(this)\n                    );\n\n                    // Override leafAmount with the received amount\n                    leafAmount = balanceAfter - balanceBefore;\n\n                    originTokenAddress = token;\n                    originNetwork = networkID;\n                }\n                // Encode metadata\n                metadata = getTokenMetadata(token);\n            }\n        }\n\n        emit BridgeEvent(\n            _LEAF_TYPE_ASSET,\n            originNetwork,\n            originTokenAddress,\n            destinationNetwork,\n            destinationAddress,\n            leafAmount,\n            metadata,\n            uint32(depositCount)\n        );\n\n        _addLeaf(\n            getLeafValue(\n                _LEAF_TYPE_ASSET,\n                originNetwork,\n                originTokenAddress,\n                destinationNetwork,\n                destinationAddress,\n                leafAmount,\n                keccak256(metadata)\n            )\n        );\n\n        // Update the new root to the global exit root manager if set by the user\n        if (forceUpdateGlobalExitRoot) {\n            _updateGlobalExitRoot();\n        }\n    }\n\n    /**\n     * @notice Bridge message and send ETH value\n     * note User/UI must be aware of the existing/available networks when choosing the destination network\n     * @param destinationNetwork Network destination\n     * @param destinationAddress Address destination\n     * @param forceUpdateGlobalExitRoot Indicates if the new global exit root is updated or not\n     * @param metadata Message metadata\n     */\n    function bridgeMessage(\n        uint32 destinationNetwork,\n        address destinationAddress,\n        bool forceUpdateGlobalExitRoot,\n        bytes calldata metadata\n    ) external payable ifNotEmergencyState {\n        // If exist a gas token, only allow call this function without value\n        if (msg.value != 0 && address(WETHToken) != address(0)) {\n            revert NoValueInMessagesOnGasTokenNetworks();\n        }\n\n        _bridgeMessage(\n            destinationNetwork,\n            destinationAddress,\n            msg.value,\n            forceUpdateGlobalExitRoot,\n            metadata\n        );\n    }\n\n    /**\n     * @notice Bridge message and send ETH value\n     * note User/UI must be aware of the existing/available networks when choosing the destination network\n     * @param destinationNetwork Network destination\n     * @param destinationAddress Address destination\n     * @param amountWETH Amount of WETH tokens\n     * @param forceUpdateGlobalExitRoot Indicates if the new global exit root is updated or not\n     * @param metadata Message metadata\n     */\n    function bridgeMessageWETH(\n        uint32 destinationNetwork,\n        address destinationAddress,\n        uint256 amountWETH,\n        bool forceUpdateGlobalExitRoot,\n        bytes calldata metadata\n    ) external ifNotEmergencyState {\n        // If native token is ether, disable this function\n        if (address(WETHToken) == address(0)) {\n            revert NativeTokenIsEther();\n        }\n\n        // Burn wETH tokens\n        WETHToken.burn(msg.sender, amountWETH);\n\n        _bridgeMessage(\n            destinationNetwork,\n            destinationAddress,\n            amountWETH,\n            forceUpdateGlobalExitRoot,\n            metadata\n        );\n    }\n\n    /**\n     * @notice Bridge message and send ETH value\n     * @param destinationNetwork Network destination\n     * @param destinationAddress Address destination\n     * @param amountEther Amount of ether along with the message\n     * @param forceUpdateGlobalExitRoot Indicates if the new global exit root is updated or not\n     * @param metadata Message metadata\n     */\n    function _bridgeMessage(\n        uint32 destinationNetwork,\n        address destinationAddress,\n        uint256 amountEther,\n        bool forceUpdateGlobalExitRoot,\n        bytes calldata metadata\n    ) internal {\n        if (destinationNetwork == networkID) {\n            revert DestinationNetworkInvalid();\n        }\n\n        emit BridgeEvent(\n            _LEAF_TYPE_MESSAGE,\n            networkID,\n            msg.sender,\n            destinationNetwork,\n            destinationAddress,\n            amountEther,\n            metadata,\n            uint32(depositCount)\n        );\n\n        _addLeaf(\n            getLeafValue(\n                _LEAF_TYPE_MESSAGE,\n                networkID,\n                msg.sender,\n                destinationNetwork,\n                destinationAddress,\n                amountEther,\n                keccak256(metadata)\n            )\n        );\n\n        // Update the new root to the global exit root manager if set by the user\n        if (forceUpdateGlobalExitRoot) {\n            _updateGlobalExitRoot();\n        }\n    }\n\n    /**\n     * @notice Verify merkle proof and withdraw tokens/ether\n     * @param smtProofLocalExitRoot Smt proof to proof the leaf against the network exit root\n     * @param smtProofRollupExitRoot Smt proof to proof the rollupLocalExitRoot against the rollups exit root\n     * @param globalIndex Global index is defined as:\n     * | 191 bits |    1 bit     |   32 bits   |     32 bits    |\n     * |    0     |  mainnetFlag | rollupIndex | localRootIndex |\n     * note that only the rollup index will be used only in case the mainnet flag is 0\n     * note that global index do not assert the unused bits to 0.\n     * This means that when synching the events, the globalIndex must be decoded the same way that in the Smart contract\n     * to avoid possible synch attacks\n     * @param mainnetExitRoot Mainnet exit root\n     * @param rollupExitRoot Rollup exit root\n     * @param originNetwork Origin network\n     * @param originTokenAddress  Origin token address, 0 address is reserved for ether\n     * @param destinationNetwork Network destination\n     * @param destinationAddress Address destination\n     * @param amount Amount of tokens\n     * @param metadata Abi encoded metadata if any, empty otherwise\n     */\n    function claimAsset(\n        bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofLocalExitRoot,\n        bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofRollupExitRoot,\n        uint256 globalIndex,\n        bytes32 mainnetExitRoot,\n        bytes32 rollupExitRoot,\n        uint32 originNetwork,\n        address originTokenAddress,\n        uint32 destinationNetwork,\n        address destinationAddress,\n        uint256 amount,\n        bytes calldata metadata\n    ) external ifNotEmergencyState {\n        // Destination network must be this networkID\n        if (destinationNetwork != networkID) {\n            revert DestinationNetworkInvalid();\n        }\n\n        // Verify leaf exist and it does not have been claimed\n        _verifyLeaf(\n            smtProofLocalExitRoot,\n            smtProofRollupExitRoot,\n            globalIndex,\n            mainnetExitRoot,\n            rollupExitRoot,\n            getLeafValue(\n                _LEAF_TYPE_ASSET,\n                originNetwork,\n                originTokenAddress,\n                destinationNetwork,\n                destinationAddress,\n                amount,\n                keccak256(metadata)\n            )\n        );\n\n        // Transfer funds\n        if (originTokenAddress == address(0)) {\n            if (address(WETHToken) == address(0)) {\n                // Ether is the native token\n                /* solhint-disable avoid-low-level-calls */\n                (bool success, ) = destinationAddress.call{value: amount}(\n                    new bytes(0)\n                );\n                if (!success) {\n                    revert EtherTransferFailed();\n                }\n            } else {\n                // Claim wETH\n                WETHToken.mint(destinationAddress, amount);\n            }\n        } else {\n            // Check if it's gas token\n            if (\n                originTokenAddress == gasTokenAddress &&\n                gasTokenNetwork == originNetwork\n            ) {\n                // Transfer gas token\n                /* solhint-disable avoid-low-level-calls */\n                (bool success, ) = destinationAddress.call{value: amount}(\n                    new bytes(0)\n                );\n                if (!success) {\n                    revert EtherTransferFailed();\n                }\n            } else {\n                // Transfer tokens\n                if (originNetwork == networkID) {\n                    // The token is an ERC20 from this network\n                    IERC20Upgradeable(originTokenAddress).safeTransfer(\n                        destinationAddress,\n                        amount\n                    );\n                } else {\n                    // The tokens is not from this network\n                    // Create a wrapper for the token if not exist yet\n                    bytes32 tokenInfoHash = keccak256(\n                        abi.encodePacked(originNetwork, originTokenAddress)\n                    );\n                    address wrappedToken = tokenInfoToWrappedToken[\n                        tokenInfoHash\n                    ];\n\n                    if (wrappedToken == address(0)) {\n                        // Get ERC20 metadata\n\n                        // Create a new wrapped erc20 using create2\n                        TokenWrapped newWrappedToken = _deployWrappedToken(\n                            tokenInfoHash,\n                            metadata\n                        );\n\n                        // Mint tokens for the destination address\n                        newWrappedToken.mint(destinationAddress, amount);\n\n                        // Create mappings\n                        tokenInfoToWrappedToken[tokenInfoHash] = address(\n                            newWrappedToken\n                        );\n\n                        wrappedTokenToTokenInfo[\n                            address(newWrappedToken)\n                        ] = TokenInformation(originNetwork, originTokenAddress);\n\n                        emit NewWrappedToken(\n                            originNetwork,\n                            originTokenAddress,\n                            address(newWrappedToken),\n                            metadata\n                        );\n                    } else {\n                        // Use the existing wrapped erc20\n                        TokenWrapped(wrappedToken).mint(\n                            destinationAddress,\n                            amount\n                        );\n                    }\n                }\n            }\n        }\n\n        emit ClaimEvent(\n            globalIndex,\n            originNetwork,\n            originTokenAddress,\n            destinationAddress,\n            amount\n        );\n    }\n\n    /**\n     * @notice Verify merkle proof and execute message\n     * If the receiving address is an EOA, the call will result as a success\n     * Which means that the amount of ether will be transferred correctly, but the message\n     * will not trigger any execution\n     * @param smtProofLocalExitRoot Smt proof to proof the leaf against the exit root\n     * @param smtProofRollupExitRoot Smt proof to proof the rollupLocalExitRoot against the rollups exit root\n     * @param globalIndex Global index is defined as:\n     * | 191 bits |    1 bit     |   32 bits   |     32 bits    |\n     * |    0     |  mainnetFlag | rollupIndex | localRootIndex |\n     * note that only the rollup index will be used only in case the mainnet flag is 0\n     * note that global index do not assert the unused bits to 0.\n     * This means that when synching the events, the globalIndex must be decoded the same way that in the Smart contract\n     * to avoid possible synch attacks\n     * @param mainnetExitRoot Mainnet exit root\n     * @param rollupExitRoot Rollup exit root\n     * @param originNetwork Origin network\n     * @param originAddress Origin address\n     * @param destinationNetwork Network destination\n     * @param destinationAddress Address destination\n     * @param amount message value\n     * @param metadata Abi encoded metadata if any, empty otherwise\n     */\n    function claimMessage(\n        bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofLocalExitRoot,\n        bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofRollupExitRoot,\n        uint256 globalIndex,\n        bytes32 mainnetExitRoot,\n        bytes32 rollupExitRoot,\n        uint32 originNetwork,\n        address originAddress,\n        uint32 destinationNetwork,\n        address destinationAddress,\n        uint256 amount,\n        bytes calldata metadata\n    ) external ifNotEmergencyState {\n        // Destination network must be this networkID\n        if (destinationNetwork != networkID) {\n            revert DestinationNetworkInvalid();\n        }\n\n        // Verify leaf exist and it does not have been claimed\n        _verifyLeaf(\n            smtProofLocalExitRoot,\n            smtProofRollupExitRoot,\n            globalIndex,\n            mainnetExitRoot,\n            rollupExitRoot,\n            getLeafValue(\n                _LEAF_TYPE_MESSAGE,\n                originNetwork,\n                originAddress,\n                destinationNetwork,\n                destinationAddress,\n                amount,\n                keccak256(metadata)\n            )\n        );\n\n        // Execute message\n        bool success;\n        if (address(WETHToken) == address(0)) {\n            // Native token is ether\n            // Transfer ether\n            /* solhint-disable avoid-low-level-calls */\n            (success, ) = destinationAddress.call{value: amount}(\n                abi.encodeCall(\n                    IBridgeMessageReceiver.onMessageReceived,\n                    (originAddress, originNetwork, metadata)\n                )\n            );\n        } else {\n            // Mint wETH tokens\n            WETHToken.mint(destinationAddress, amount);\n\n            // Execute message\n            /* solhint-disable avoid-low-level-calls */\n            (success, ) = destinationAddress.call(\n                abi.encodeCall(\n                    IBridgeMessageReceiver.onMessageReceived,\n                    (originAddress, originNetwork, metadata)\n                )\n            );\n        }\n\n        if (!success) {\n            revert MessageFailed();\n        }\n\n        emit ClaimEvent(\n            globalIndex,\n            originNetwork,\n            originAddress,\n            destinationAddress,\n            amount\n        );\n    }\n\n    /**\n     * @notice Returns the precalculated address of a wrapper using the token information\n     * Note Updating the metadata of a token is not supported.\n     * Since the metadata has relevance in the address deployed, this function will not return a valid\n     * wrapped address if the metadata provided is not the original one.\n     * @param originNetwork Origin network\n     * @param originTokenAddress Origin token address, 0 address is reserved for ether\n     * @param name Name of the token\n     * @param symbol Symbol of the token\n     * @param decimals Decimals of the token\n     */\n    function precalculatedWrapperAddress(\n        uint32 originNetwork,\n        address originTokenAddress,\n        string memory name,\n        string memory symbol,\n        uint8 decimals\n    ) public view returns (address) {\n        bytes32 salt = keccak256(\n            abi.encodePacked(originNetwork, originTokenAddress)\n        );\n\n        bytes32 hashCreate2 = keccak256(\n            abi.encodePacked(\n                bytes1(0xff),\n                address(this),\n                salt,\n                keccak256(\n                    abi.encodePacked(\n                        BASE_INIT_BYTECODE_WRAPPED_TOKEN,\n                        abi.encode(name, symbol, decimals)\n                    )\n                )\n            )\n        );\n\n        // Last 20 bytes of hash to address\n        return address(uint160(uint256(hashCreate2)));\n    }\n\n    /**\n     * @notice Returns the address of a wrapper using the token information if already exist\n     * @param originNetwork Origin network\n     * @param originTokenAddress Origin token address, 0 address is reserved for ether\n     */\n    function getTokenWrappedAddress(\n        uint32 originNetwork,\n        address originTokenAddress\n    ) external view returns (address) {\n        return\n            tokenInfoToWrappedToken[\n                keccak256(abi.encodePacked(originNetwork, originTokenAddress))\n            ];\n    }\n\n    /**\n     * @notice Function to activate the emergency state\n     \" Only can be called by the Polygon ZK-EVM in extreme situations\n     */\n    function activateEmergencyState() external onlyRollupManager {\n        _activateEmergencyState();\n    }\n\n    /**\n     * @notice Function to deactivate the emergency state\n     \" Only can be called by the Polygon ZK-EVM\n     */\n    function deactivateEmergencyState() external onlyRollupManager {\n        _deactivateEmergencyState();\n    }\n\n    /**\n     * @notice Verify leaf and checks that it has not been claimed\n     * @param smtProofLocalExitRoot Smt proof\n     * @param smtProofRollupExitRoot Smt proof\n     * @param globalIndex Index of the leaf\n     * @param mainnetExitRoot Mainnet exit root\n     * @param rollupExitRoot Rollup exit root\n     * @param leafValue leaf value\n     */\n    function _verifyLeaf(\n        bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofLocalExitRoot,\n        bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofRollupExitRoot,\n        uint256 globalIndex,\n        bytes32 mainnetExitRoot,\n        bytes32 rollupExitRoot,\n        bytes32 leafValue\n    ) internal {\n        // Check blockhash where the global exit root was set\n        // Note that previusly timestamps were setted, since in only checked if != 0 it's ok\n        uint256 blockHashGlobalExitRoot = globalExitRootManager\n            .globalExitRootMap(\n                GlobalExitRootLib.calculateGlobalExitRoot(\n                    mainnetExitRoot,\n                    rollupExitRoot\n                )\n            );\n\n        // check that this global exit root exist\n        if (blockHashGlobalExitRoot == 0) {\n            revert GlobalExitRootInvalid();\n        }\n\n        uint32 leafIndex;\n        uint32 sourceBridgeNetwork;\n\n        // Get origin network from global index\n        if (globalIndex & _GLOBAL_INDEX_MAINNET_FLAG != 0) {\n            // the network is mainnet, therefore sourceBridgeNetwork is 0\n\n            // Last 32 bits are leafIndex\n            leafIndex = uint32(globalIndex);\n\n            if (\n                !verifyMerkleProof(\n                    leafValue,\n                    smtProofLocalExitRoot,\n                    leafIndex,\n                    mainnetExitRoot\n                )\n            ) {\n                revert InvalidSmtProof();\n            }\n        } else {\n            // the network is a rollup, therefore sourceBridgeNetwork must be decoded\n            uint32 indexRollup = uint32(globalIndex >> 32);\n            sourceBridgeNetwork = indexRollup + 1;\n\n            // Last 32 bits are leafIndex\n            leafIndex = uint32(globalIndex);\n\n            // Verify merkle proof agains rollup exit root\n            if (\n                !verifyMerkleProof(\n                    calculateRoot(leafValue, smtProofLocalExitRoot, leafIndex),\n                    smtProofRollupExitRoot,\n                    indexRollup,\n                    rollupExitRoot\n                )\n            ) {\n                revert InvalidSmtProof();\n            }\n        }\n\n        // Set and check nullifier\n        _setAndCheckClaimed(leafIndex, sourceBridgeNetwork);\n    }\n\n    /**\n     * @notice Function to check if an index is claimed or not\n     * @param leafIndex Index\n     * @param sourceBridgeNetwork Origin network\n     */\n    function isClaimed(\n        uint32 leafIndex,\n        uint32 sourceBridgeNetwork\n    ) external view returns (bool) {\n        uint256 globalIndex;\n\n        // For consistency with the previous setted nullifiers\n        if (\n            networkID == _MAINNET_NETWORK_ID &&\n            sourceBridgeNetwork == _ZKEVM_NETWORK_ID\n        ) {\n            globalIndex = uint256(leafIndex);\n        } else {\n            globalIndex =\n                uint256(leafIndex) +\n                uint256(sourceBridgeNetwork) *\n                _MAX_LEAFS_PER_NETWORK;\n        }\n        (uint256 wordPos, uint256 bitPos) = _bitmapPositions(globalIndex);\n        uint256 mask = (1 << bitPos);\n        return (claimedBitMap[wordPos] & mask) == mask;\n    }\n\n    /**\n     * @notice Function to check that an index is not claimed and set it as claimed\n     * @param leafIndex Index\n     * @param sourceBridgeNetwork Origin network\n     */\n    function _setAndCheckClaimed(\n        uint32 leafIndex,\n        uint32 sourceBridgeNetwork\n    ) private {\n        uint256 globalIndex;\n\n        // For consistency with the previous setted nullifiers\n        if (\n            networkID == _MAINNET_NETWORK_ID &&\n            sourceBridgeNetwork == _ZKEVM_NETWORK_ID\n        ) {\n            globalIndex = uint256(leafIndex);\n        } else {\n            globalIndex =\n                uint256(leafIndex) +\n                uint256(sourceBridgeNetwork) *\n                _MAX_LEAFS_PER_NETWORK;\n        }\n        (uint256 wordPos, uint256 bitPos) = _bitmapPositions(globalIndex);\n        uint256 mask = 1 << bitPos;\n        uint256 flipped = claimedBitMap[wordPos] ^= mask;\n        if (flipped & mask == 0) {\n            revert AlreadyClaimed();\n        }\n    }\n\n    /**\n     * @notice Function to update the globalExitRoot if the last deposit is not submitted\n     */\n    function updateGlobalExitRoot() external {\n        if (lastUpdatedDepositCount < depositCount) {\n            _updateGlobalExitRoot();\n        }\n    }\n\n    /**\n     * @notice Function to update the globalExitRoot\n     */\n    function _updateGlobalExitRoot() internal {\n        lastUpdatedDepositCount = uint32(depositCount);\n        globalExitRootManager.updateExitRoot(getRoot());\n    }\n\n    /**\n     * @notice Function decode an index into a wordPos and bitPos\n     * @param index Index\n     */\n    function _bitmapPositions(\n        uint256 index\n    ) private pure returns (uint256 wordPos, uint256 bitPos) {\n        wordPos = uint248(index >> 8);\n        bitPos = uint8(index);\n    }\n\n    /**\n     * @notice Function to call token permit method of extended ERC20\n     + @param token ERC20 token address\n     * @param amount Quantity that is expected to be allowed\n     * @param permitData Raw data of the call `permit` of the token\n     */\n    function _permit(\n        address token,\n        uint256 amount,\n        bytes calldata permitData\n    ) internal {\n        bytes4 sig = bytes4(permitData[:4]);\n        if (sig == _PERMIT_SIGNATURE) {\n            (\n                address owner,\n                address spender,\n                uint256 value,\n                uint256 deadline,\n                uint8 v,\n                bytes32 r,\n                bytes32 s\n            ) = abi.decode(\n                    permitData[4:],\n                    (\n                        address,\n                        address,\n                        uint256,\n                        uint256,\n                        uint8,\n                        bytes32,\n                        bytes32\n                    )\n                );\n            if (owner != msg.sender) {\n                revert NotValidOwner();\n            }\n            if (spender != address(this)) {\n                revert NotValidSpender();\n            }\n\n            if (value != amount) {\n                revert NotValidAmount();\n            }\n\n            // we call without checking the result, in case it fails and he doesn't have enough balance\n            // the following transferFrom should be fail. This prevents DoS attacks from using a signature\n            // before the smartcontract call\n            /* solhint-disable avoid-low-level-calls */\n            address(token).call(\n                abi.encodeWithSelector(\n                    _PERMIT_SIGNATURE,\n                    owner,\n                    spender,\n                    value,\n                    deadline,\n                    v,\n                    r,\n                    s\n                )\n            );\n        } else {\n            if (sig != _PERMIT_SIGNATURE_DAI) {\n                revert NotValidSignature();\n            }\n\n            (\n                address holder,\n                address spender,\n                uint256 nonce,\n                uint256 expiry,\n                bool allowed,\n                uint8 v,\n                bytes32 r,\n                bytes32 s\n            ) = abi.decode(\n                    permitData[4:],\n                    (\n                        address,\n                        address,\n                        uint256,\n                        uint256,\n                        bool,\n                        uint8,\n                        bytes32,\n                        bytes32\n                    )\n                );\n\n            if (holder != msg.sender) {\n                revert NotValidOwner();\n            }\n\n            if (spender != address(this)) {\n                revert NotValidSpender();\n            }\n\n            // we call without checking the result, in case it fails and he doesn't have enough balance\n            // the following transferFrom should be fail. This prevents DoS attacks from using a signature\n            // before the smartcontract call\n            /* solhint-disable avoid-low-level-calls */\n            address(token).call(\n                abi.encodeWithSelector(\n                    _PERMIT_SIGNATURE_DAI,\n                    holder,\n                    spender,\n                    nonce,\n                    expiry,\n                    allowed,\n                    v,\n                    r,\n                    s\n                )\n            );\n        }\n    }\n\n    /**\n     * @notice Internal function that uses create2 to deploy the wrapped tokens\n     * @param salt Salt used in create2 params,\n     * tokenInfoHash will be used as salt for all wrappeds except for bridge native WETH, that will be bytes32(0)\n     * @param constructorArgs Encoded constructor args for the wrapped token\n     */\n    function _deployWrappedToken(\n        bytes32 salt,\n        bytes memory constructorArgs\n    ) internal returns (TokenWrapped newWrappedToken) {\n        bytes memory initBytecode = abi.encodePacked(\n            BASE_INIT_BYTECODE_WRAPPED_TOKEN,\n            constructorArgs\n        );\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            newWrappedToken := create2(\n                0,\n                add(initBytecode, 0x20),\n                mload(initBytecode),\n                salt\n            )\n        }\n        if (address(newWrappedToken) == address(0))\n            revert FailedTokenWrappedDeployment();\n    }\n\n    // Helpers to safely get the metadata from a token, inspired by https://github.com/traderjoe-xyz/joe-core/blob/main/contracts/MasterChefJoeV3.sol#L55-L95\n\n    /**\n     * @notice Provides a safe ERC20.symbol version which returns 'NO_SYMBOL' as fallback string\n     * @param token The address of the ERC-20 token contract\n     */\n    function _safeSymbol(address token) internal view returns (string memory) {\n        (bool success, bytes memory data) = address(token).staticcall(\n            abi.encodeCall(IERC20MetadataUpgradeable.symbol, ())\n        );\n        return success ? _returnDataToString(data) : \"NO_SYMBOL\";\n    }\n\n    /**\n     * @notice  Provides a safe ERC20.name version which returns 'NO_NAME' as fallback string.\n     * @param token The address of the ERC-20 token contract.\n     */\n    function _safeName(address token) internal view returns (string memory) {\n        (bool success, bytes memory data) = address(token).staticcall(\n            abi.encodeCall(IERC20MetadataUpgradeable.name, ())\n        );\n        return success ? _returnDataToString(data) : \"NO_NAME\";\n    }\n\n    /**\n     * @notice Provides a safe ERC20.decimals version which returns '18' as fallback value.\n     * Note Tokens with (decimals > 255) are not supported\n     * @param token The address of the ERC-20 token contract\n     */\n    function _safeDecimals(address token) internal view returns (uint8) {\n        (bool success, bytes memory data) = address(token).staticcall(\n            abi.encodeCall(IERC20MetadataUpgradeable.decimals, ())\n        );\n        return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;\n    }\n\n    /**\n     * @notice Function to convert returned data to string\n     * returns 'NOT_VALID_ENCODING' as fallback value.\n     * @param data returned data\n     */\n    function _returnDataToString(\n        bytes memory data\n    ) internal pure returns (string memory) {\n        if (data.length >= 64) {\n            return abi.decode(data, (string));\n        } else if (data.length == 32) {\n            // Since the strings on bytes32 are encoded left-right, check the first zero in the data\n            uint256 nonZeroBytes;\n            while (nonZeroBytes < 32 && data[nonZeroBytes] != 0) {\n                nonZeroBytes++;\n            }\n\n            // If the first one is 0, we do not handle the encoding\n            if (nonZeroBytes == 0) {\n                return \"NOT_VALID_ENCODING\";\n            }\n            // Create a byte array with nonZeroBytes length\n            bytes memory bytesArray = new bytes(nonZeroBytes);\n            for (uint256 i = 0; i < nonZeroBytes; i++) {\n                bytesArray[i] = data[i];\n            }\n            return string(bytesArray);\n        } else {\n            return \"NOT_VALID_ENCODING\";\n        }\n    }\n\n    /**\n     * @notice Returns the encoded token metadata\n     * @param token Address of the token\n     */\n\n    function getTokenMetadata(\n        address token\n    ) public view returns (bytes memory) {\n        return\n            abi.encode(\n                _safeName(token),\n                _safeSymbol(token),\n                _safeDecimals(token)\n            );\n    }\n\n    /**\n     * @notice Returns the precalculated address of a wrapper using the token address\n     * Note Updating the metadata of a token is not supported.\n     * Since the metadata has relevance in the address deployed, this function will not return a valid\n     * wrapped address if the metadata provided is not the original one.\n     * @param originNetwork Origin network\n     * @param originTokenAddress Origin token address, 0 address is reserved for ether\n     * @param token Address of the token to calculate the wrapper address\n     */\n    function calculateTokenWrapperAddress(\n        uint32 originNetwork,\n        address originTokenAddress,\n        address token\n    ) external view returns (address) {\n        return\n            precalculatedWrapperAddress(\n                originNetwork,\n                originTokenAddress,\n                _safeName(token),\n                _safeSymbol(token),\n                _safeDecimals(token)\n            );\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 999
      },
      "evmVersion": "shanghai",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}