{"file_path":"Bridge.sol","creation_status":"success","source_code":"// Dependency file: contracts/zeppelin/upgradable/Initializable.sol\r\n\r\n// SPDX-License-Identifier: MIT\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n/**\r\n * @title Initializable\r\n *\r\n * @dev Helper contract to support initializer functions. To use it, replace\r\n * the constructor with a function that has the `initializer` modifier.\r\n * WARNING: Unlike constructors, initializer functions must be manually\r\n * invoked. This applies both to deploying an Initializable contract, as well\r\n * as extending an Initializable contract via inheritance.\r\n * WARNING: When used with inheritance, manual care must be taken to not invoke\r\n * a parent initializer twice, or ensure that all initializers are idempotent,\r\n * because this is not dealt with automatically as with constructors.\r\n */\r\ncontract Initializable {\r\n\r\n  /**\r\n   * @dev Indicates that the contract has been initialized.\r\n   */\r\n  bool private initialized;\r\n\r\n  /**\r\n   * @dev Indicates that the contract is in the process of being initialized.\r\n   */\r\n  bool private initializing;\r\n\r\n  /**\r\n   * @dev Modifier to use in the initializer function of a contract.\r\n   */\r\n  modifier initializer() {\r\n    require(initializing || !initialized, \"Contract instance is already initialized\");\r\n\r\n    bool isTopLevelCall = !initializing;\r\n    if (isTopLevelCall) {\r\n      initializing = true;\r\n      initialized = true;\r\n    }\r\n\r\n    _;\r\n\r\n    if (isTopLevelCall) {\r\n      initializing = false;\r\n    }\r\n  }\r\n\r\n  // Reserved storage space to allow for layout changes in the future.\r\n  uint256[50] private ______gap;\r\n}\r\n\r\n// Dependency file: contracts/zeppelin/upgradable/utils/ReentrancyGuard.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n// import \"contracts/zeppelin/upgradable/Initializable.sol\";\r\n\r\n/**\r\n * @title Helps contracts guard against reentrancy attacks.\r\n * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io>\r\n * @dev If you mark a function `nonReentrant`, you should also\r\n * mark it `external`.\r\n */\r\ncontract ReentrancyGuard is Initializable {\r\n    /// @dev counter to allow mutex lock with only one SSTORE operation\r\n    uint256 private _guardCounter;\r\n\r\n    function initialize() public initializer {\r\n        // The counter starts at one to prevent changing it from zero to a non-zero\r\n        // value, which is a more expensive operation.\r\n        _guardCounter = 1;\r\n    }\r\n\r\n    /**\r\n     * @dev Prevents a contract from calling itself, directly or indirectly.\r\n     * Calling a `nonReentrant` function from another `nonReentrant`\r\n     * function is not supported. It is possible to prevent this from happening\r\n     * by making the `nonReentrant` function external, and make it call a\r\n     * `private` function that does the actual work.\r\n     */\r\n    modifier nonReentrant() {\r\n        _guardCounter += 1;\r\n        uint256 localCounter = _guardCounter;\r\n        _;\r\n        require(localCounter == _guardCounter, \"ReentrancyGuard: no reentrant allowed\");\r\n    }\r\n}\r\n\r\n// Dependency file: contracts/zeppelin/GSN/Context.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n/*\r\n * @dev Provides information about the current execution context, including the\r\n * sender of the transaction and its data. While these are generally available\r\n * via msg.sender and msg.data, they should not be accessed in such a direct\r\n * manner, since when dealing with GSN meta-transactions the account sending and\r\n * paying for execution may not be the actual sender (as far as an application\r\n * is concerned).\r\n *\r\n * This contract is only required for intermediate, library-like contracts.\r\n */\r\nabstract contract  Context {\r\n\r\n    function _msgSender() internal view returns (address payable) {\r\n        return msg.sender;\r\n    }\r\n\r\n    function _msgData() internal view returns (bytes memory) {\r\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\r\n        return msg.data;\r\n    }\r\n}\r\n\r\n\r\n// Dependency file: contracts/zeppelin/access/Roles.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n/**\r\n * @title Roles\r\n * @dev Library for managing addresses assigned to a Role.\r\n */\r\nlibrary Roles {\r\n    struct Role {\r\n        mapping (address => bool) bearer;\r\n    }\r\n\r\n    /**\r\n     * @dev Give an account access to this role.\r\n     */\r\n    function add(Role storage role, address account) internal {\r\n        require(!has(role, account), \"Roles: account already has role\");\r\n        role.bearer[account] = true;\r\n    }\r\n\r\n    /**\r\n     * @dev Remove an account's access to this role.\r\n     */\r\n    function remove(Role storage role, address account) internal {\r\n        require(has(role, account), \"Roles: account doesn't have role\");\r\n        role.bearer[account] = false;\r\n    }\r\n\r\n    /**\r\n     * @dev Check if an account has this role.\r\n     * @return bool\r\n     */\r\n    function has(Role storage role, address account) internal view returns (bool) {\r\n        require(account != address(0), \"Roles: account is the zero address\");\r\n        return role.bearer[account];\r\n    }\r\n}\r\n\r\n\r\n// Dependency file: contracts/zeppelin/upgradable/access/roles/UpgradablePauserRole.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n// import \"contracts/zeppelin/upgradable/Initializable.sol\";\r\n\r\n// import \"contracts/zeppelin/GSN/Context.sol\";\r\n// import \"contracts/zeppelin/access/Roles.sol\";\r\n\r\ncontract UpgradablePauserRole is Initializable, Context {\r\n    using Roles for Roles.Role;\r\n\r\n    event PauserAdded(address indexed account);\r\n    event PauserRemoved(address indexed account);\r\n\r\n    Roles.Role private _pausers;\r\n\r\n    function __PauserRol_init(address sender) public initializer {\r\n        if (!isPauser(sender)) {\r\n            _addPauser(sender);\r\n        }\r\n    }\r\n\r\n    modifier onlyPauser() {\r\n        require(isPauser(_msgSender()), \"PauserRole: caller doesn't have the role\");\r\n        _;\r\n    }\r\n\r\n    function isPauser(address account) public view returns (bool) {\r\n        return _pausers.has(account);\r\n    }\r\n\r\n    function addPauser(address account) public onlyPauser {\r\n        _addPauser(account);\r\n    }\r\n\r\n    function renouncePauser() public {\r\n        _removePauser(_msgSender());\r\n    }\r\n\r\n    function _addPauser(address account) internal {\r\n        _pausers.add(account);\r\n        emit PauserAdded(account);\r\n    }\r\n\r\n    function _removePauser(address account) internal {\r\n        _pausers.remove(account);\r\n        emit PauserRemoved(account);\r\n    }\r\n}\r\n\r\n\r\n// Dependency file: contracts/zeppelin/upgradable/lifecycle/UpgradablePausable.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n// import \"contracts/zeppelin/upgradable/Initializable.sol\";\r\n\r\n// import \"contracts/zeppelin/GSN/Context.sol\";\r\n// import \"contracts/zeppelin/upgradable/access/roles/UpgradablePauserRole.sol\";\r\n\r\n/**\r\n * @dev Contract module which allows children to implement an emergency stop\r\n * mechanism that can be triggered by an authorized account.\r\n *\r\n * This module is used through inheritance. It will make available the\r\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\r\n * the functions of your contract. Note that they will not be pausable by\r\n * simply including this module, only once the modifiers are put in place.\r\n */\r\ncontract UpgradablePausable is Initializable, Context, UpgradablePauserRole {\r\n    /**\r\n     * @dev Emitted when the pause is triggered by a pauser (`account`).\r\n     */\r\n    event Paused(address account);\r\n\r\n    /**\r\n     * @dev Emitted when the pause is lifted by a pauser (`account`).\r\n     */\r\n    event Unpaused(address account);\r\n\r\n    bool private _paused;\r\n\r\n    /**\r\n     * @dev Initializes the contract in unpaused state. Assigns the Pauser role\r\n     * to the deployer.\r\n     */\r\n    function __Pausable_init(address sender) public initializer {\r\n        UpgradablePauserRole.__PauserRol_init(sender);\r\n\r\n        _paused = false;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns true if the contract is paused, and false otherwise.\r\n     */\r\n    function paused() public view returns (bool) {\r\n        return _paused;\r\n    }\r\n\r\n    /**\r\n     * @dev Modifier to make a function callable only when the contract is not paused.\r\n     */\r\n    modifier whenNotPaused() {\r\n        require(!_paused, \"Pausable: paused\");\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Modifier to make a function callable only when the contract is paused.\r\n     */\r\n    modifier whenPaused() {\r\n        require(_paused, \"Pausable: not paused\");\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Called by a pauser to pause, triggers stopped state.\r\n     */\r\n    function pause() public onlyPauser whenNotPaused {\r\n        _paused = true;\r\n        emit Paused(_msgSender());\r\n    }\r\n\r\n    /**\r\n     * @dev Called by a pauser to unpause, returns to normal state.\r\n     */\r\n    function unpause() public onlyPauser whenPaused {\r\n        _paused = false;\r\n        emit Unpaused(_msgSender());\r\n    }\r\n}\r\n\r\n\r\n// Dependency file: contracts/zeppelin/upgradable/ownership/UpgradableOwnable.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n// import \"contracts/zeppelin/upgradable/Initializable.sol\";\r\n\r\n// import \"contracts/zeppelin/GSN/Context.sol\";\r\n\r\n/**\r\n * @dev Contract module which provides a basic access control mechanism, where\r\n * there is an account (an owner) that can be granted exclusive access to\r\n * specific functions.\r\n *\r\n * This module is used through inheritance. It will make available the modifier\r\n * `onlyOwner`, which can be aplied to your functions to restrict their use to\r\n * the owner.\r\n */\r\ncontract UpgradableOwnable is Initializable, Context {\r\n    address private _owner;\r\n\r\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\r\n\r\n    /**\r\n     * @dev Initializes the contract setting the deployer as the initial owner.\r\n     */\r\n    function initialize(address sender) public initializer {\r\n        _owner = sender;\r\n        emit OwnershipTransferred(address(0), _owner);\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the address of the current owner.\r\n     */\r\n    function owner() public view returns (address) {\r\n        return _owner;\r\n    }\r\n\r\n    /**\r\n     * @dev Throws if called by any account other than the owner.\r\n     */\r\n    modifier onlyOwner() {\r\n        require(isOwner(), \"Ownable: caller is not the owner\");\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns true if the caller is the current owner.\r\n     */\r\n    function isOwner() public view returns (bool) {\r\n        return _msgSender() == _owner;\r\n    }\r\n\r\n    /**\r\n     * @dev Leaves the contract without owner. It will not be possible to call\r\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\r\n     *\r\n     * > Note: Renouncing ownership will leave the contract without an owner,\r\n     * thereby removing any functionality that is only available to the owner.\r\n     */\r\n    function renounceOwnership() public onlyOwner {\r\n        emit OwnershipTransferred(_owner, address(0));\r\n        _owner = address(0);\r\n    }\r\n\r\n    /**\r\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\r\n     * Can only be called by the current owner.\r\n     */\r\n    function transferOwnership(address newOwner) public onlyOwner {\r\n        _transferOwnership(newOwner);\r\n    }\r\n\r\n    /**\r\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\r\n     */\r\n    function _transferOwnership(address newOwner) internal {\r\n        require(newOwner != address(0), \"Ownable: new owner is zero address\");\r\n        emit OwnershipTransferred(_owner, newOwner);\r\n        _owner = newOwner;\r\n    }\r\n\r\n}\r\n\r\n\r\n// Dependency file: contracts/zeppelin/introspection/IERC1820Registry.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n/**\r\n * @dev Interface of the global ERC1820 Registry, as defined in the\r\n * https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register\r\n * implementers for interfaces in this registry, as well as query support.\r\n *\r\n * Implementers may be shared by multiple accounts, and can also implement more\r\n * than a single interface for each account. Contracts can implement interfaces\r\n * for themselves, but externally-owned accounts (EOA) must delegate this to a\r\n * contract.\r\n *\r\n * {IERC165} interfaces can also be queried via the registry.\r\n *\r\n * For an in-depth explanation and source code analysis, see the EIP text.\r\n */\r\ninterface IERC1820Registry {\r\n    /**\r\n     * @dev Sets `newManager` as the manager for `account`. A manager of an\r\n     * account is able to set interface implementers for it.\r\n     *\r\n     * By default, each account is its own manager. Passing a value of `0x0` in\r\n     * `newManager` will reset the manager to this initial state.\r\n     *\r\n     * Emits a {ManagerChanged} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the caller must be the current manager for `account`.\r\n     */\r\n    function setManager(address account, address newManager) external;\r\n\r\n    /**\r\n     * @dev Returns the manager for `account`.\r\n     *\r\n     * See {setManager}.\r\n     */\r\n    function getManager(address account) external view returns (address);\r\n\r\n    /**\r\n     * @dev Sets the `implementer` contract as `account`'s implementer for\r\n     * `interfaceHash`.\r\n     *\r\n     * `account` being the zero address is an alias for the caller's address.\r\n     * The zero address can also be used in `implementer` to remove an old one.\r\n     *\r\n     * See {interfaceHash} to learn how these are created.\r\n     *\r\n     * Emits an {InterfaceImplementerSet} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the caller must be the current manager for `_account`.\r\n     * - `_interfaceHash` must not be an {IERC165} interface id (i.e. it must not\r\n     * end in 28 zeroes).\r\n     * - `_implementer` must implement {IERC1820Implementer} and return true when\r\n     * queried for support, unless `implementer` is the caller. See\r\n     * {IERC1820Implementer-canImplementInterfaceForAddress}.\r\n     */\r\n    function setInterfaceImplementer(address _account, bytes32 _interfaceHash, address _implementer) external;\r\n\r\n    /**\r\n     * @dev Returns the implementer of `_interfaceHash` for `_account`. If no such\r\n     * implementer is registered, returns the zero address.\r\n     *\r\n     * If `_interfaceHash` is an {IERC165} interface id (i.e. it ends with 28\r\n     * zeroes), `_account` will be queried for support of it.\r\n     *\r\n     * `account` being the zero address is an alias for the caller's address.\r\n     */\r\n    function getInterfaceImplementer(address _account, bytes32 _interfaceHash) external view returns (address);\r\n\r\n    /**\r\n     * @dev Returns the interface hash for an `interfaceName`, as defined in the\r\n     * corresponding\r\n     * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].\r\n     */\r\n    function interfaceHash(string calldata interfaceName) external pure returns (bytes32);\r\n\r\n    /**\r\n     *  @notice Updates the cache with whether the contract implements an ERC165 interface or not.\r\n     *  @param account Address of the contract for which to update the cache.\r\n     *  @param interfaceId ERC165 interface for which to update the cache.\r\n     */\r\n    function updateERC165Cache(address account, bytes4 interfaceId) external;\r\n\r\n    /**\r\n     *  @notice Checks whether a contract implements an ERC165 interface or not.\r\n     *  If the result is not cached a direct lookup on the contract address is performed.\r\n     *  If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling\r\n     *  {updateERC165Cache} with the contract address.\r\n     *  @param account Address of the contract to check.\r\n     *  @param interfaceId ERC165 interface to check.\r\n     *  @return True if `account` implements `interfaceId`, false otherwise.\r\n     */\r\n    function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);\r\n\r\n    /**\r\n     *  @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.\r\n     *  @param account Address of the contract to check.\r\n     *  @param interfaceId ERC165 interface to check.\r\n     *  @return True if `account` implements `interfaceId`, false otherwise.\r\n     */\r\n    function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);\r\n\r\n    event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);\r\n\r\n    event ManagerChanged(address indexed account, address indexed newManager);\r\n}\r\n\r\n\r\n// Dependency file: contracts/zeppelin/token/ERC777/IERC777Recipient.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n/**\r\n * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.\r\n *\r\n * Accounts can be notified of `IERC777` tokens being sent to them by having a\r\n * contract implement this interface (contract holders can be their own\r\n * implementer) and registering it on the\r\n * [ERC1820 global registry](https://eips.ethereum.org/EIPS/eip-1820).\r\n *\r\n * See `IERC1820Registry` and `ERC1820Implementer`.\r\n */\r\ninterface IERC777Recipient {\r\n    /**\r\n     * @dev Called by an `IERC777` token contract whenever tokens are being\r\n     * moved or created into a registered account (`to`). The type of operation\r\n     * is conveyed by `from` being the zero address or not.\r\n     *\r\n     * This call occurs _after_ the token contract's state is updated, so\r\n     * `IERC777.balanceOf`, etc., can be used to query the post-operation state.\r\n     *\r\n     * This function may revert to prevent the operation from being executed.\r\n     */\r\n    function tokensReceived(\r\n        address operator,\r\n        address from,\r\n        address to,\r\n        uint amount,\r\n        bytes calldata userData,\r\n        bytes calldata operatorData\r\n    ) external;\r\n}\r\n\r\n\r\n// Dependency file: contracts/zeppelin/token/ERC20/IERC20.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n/**\r\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\r\n * the optional functions; to access them see {ERC20Detailed}.\r\n */\r\ninterface IERC20 {\r\n    /**\r\n     * @dev Returns the amount of tokens in existence.\r\n     */\r\n    function totalSupply() external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens owned by `account`.\r\n     */\r\n    function balanceOf(address account) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transfer(address recipient, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Returns the remaining number of tokens that `spender` will be\r\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\r\n     * zero by default.\r\n     *\r\n     * This value changes when {approve} or {transferFrom} are called.\r\n     */\r\n    function allowance(address owner, address spender) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\r\n     * that someone may use both the old and the new allowance by unfortunate\r\n     * transaction ordering. One possible solution to mitigate this race\r\n     * condition is to first reduce the spender's allowance to 0 and set the\r\n     * desired value afterwards:\r\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\r\n     *\r\n     * Emits an {Approval} event.\r\n     */\r\n    function approve(address spender, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\r\n     * allowance mechanism. `amount` is then deducted from the caller's\r\n     * allowance.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\r\n     * another (`to`).\r\n     *\r\n     * Note that `value` may be zero.\r\n     */\r\n    event Transfer(address indexed from, address indexed to, uint256 value);\r\n\r\n    /**\r\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\r\n     * a call to {approve}. `value` is the new allowance.\r\n     */\r\n    event Approval(address indexed owner, address indexed spender, uint256 value);\r\n}\r\n\r\n\r\n// Dependency file: contracts/zeppelin/math/SafeMath.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n/**\r\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\r\n * checks.\r\n *\r\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\r\n * in bugs, because programmers usually assume that an overflow raises an\r\n * error, which is the standard behavior in high level programming languages.\r\n * `SafeMath` restores this intuition by reverting the transaction when an\r\n * operation overflows.\r\n *\r\n * Using this library instead of the unchecked operations eliminates an entire\r\n * class of bugs, so it's recommended to use it always.\r\n */\r\nlibrary SafeMath {\r\n    /**\r\n     * @dev Returns the addition of two unsigned integers, reverting on\r\n     * overflow.\r\n     *\r\n     * Counterpart to Solidity's `+` operator.\r\n     *\r\n     * Requirements:\r\n     * - Addition cannot overflow.\r\n     */\r\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        uint256 c = a + b;\r\n        require(c >= a, \"SafeMath: addition overflow\");\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the subtraction of two unsigned integers, reverting on\r\n     * overflow (when the result is negative).\r\n     *\r\n     * Counterpart to Solidity's `-` operator.\r\n     *\r\n     * Requirements:\r\n     * - Subtraction cannot overflow.\r\n     */\r\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return sub(a, b, \"SafeMath: subtraction overflow\");\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\r\n     * overflow (when the result is negative).\r\n     *\r\n     * Counterpart to Solidity's `-` operator.\r\n     *\r\n     * Requirements:\r\n     * - Subtraction cannot overflow.\r\n     *\r\n     * _Available since v2.4.0._\r\n     */\r\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\r\n        require(b <= a, errorMessage);\r\n        uint256 c = a - b;\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the multiplication of two unsigned integers, reverting on\r\n     * overflow.\r\n     *\r\n     * Counterpart to Solidity's `*` operator.\r\n     *\r\n     * Requirements:\r\n     * - Multiplication cannot overflow.\r\n     */\r\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\r\n        // benefit is lost if 'b' is also tested.\r\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\r\n        if (a == 0) {\r\n            return 0;\r\n        }\r\n\r\n        uint256 c = a * b;\r\n        require(c / a == b, \"SafeMath: multiplication overflow\");\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the integer division of two unsigned integers. Reverts on\r\n     * division by zero. The result is rounded towards zero.\r\n     *\r\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\r\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\r\n     * uses an invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     */\r\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return div(a, b, \"SafeMath: division by zero\");\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\r\n     * division by zero. The result is rounded towards zero.\r\n     *\r\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\r\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\r\n     * uses an invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     *\r\n     * _Available since v2.4.0._\r\n     */\r\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\r\n        // Solidity only automatically asserts when dividing by 0\r\n        require(b > 0, errorMessage);\r\n        uint256 c = a / b;\r\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\r\n     * Reverts when dividing by zero.\r\n     *\r\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\r\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\r\n     * invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     */\r\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return mod(a, b, \"SafeMath: modulo by zero\");\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\r\n     * Reverts with custom message when dividing by zero.\r\n     *\r\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\r\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\r\n     * invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     *\r\n     * _Available since v2.4.0._\r\n     */\r\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\r\n        require(b != 0, errorMessage);\r\n        return a % b;\r\n    }\r\n}\r\n\r\n\r\n// Dependency file: contracts/zeppelin/utils/Address.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n/**\r\n * @dev Collection of functions related to the address type,\r\n */\r\nlibrary Address {\r\n    /**\r\n     * @dev Returns true if `account` is a contract.\r\n     *\r\n     * [IMPORTANT]\r\n     * ====\r\n     * It is unsafe to assume that an address for which this function returns\r\n     * false is an externally-owned account (EOA) and not a contract.\r\n     *\r\n     * Among others, `isContract` will return false for the following\r\n     * types of addresses:\r\n     *\r\n     *  - an externally-owned account\r\n     *  - a contract in construction\r\n     *  - an address where a contract will be created\r\n     *  - an address where a contract lived, but was destroyed\r\n     * ====\r\n     */\r\n    function isContract(address account) internal view returns (bool) {\r\n        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\r\n        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\r\n        // for accounts without code, i.e. `keccak256('')`\r\n        bytes32 codehash;\r\n        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\r\n        // solhint-disable-next-line no-inline-assembly\r\n        assembly { codehash := extcodehash(account) }\r\n        return (codehash != accountHash && codehash != 0x0);\r\n    }\r\n\r\n     /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a delegate call.\r\n     *\r\n     * _Available since v3.4._\r\n     */\r\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\r\n        return functionDelegateCall(target, data, \"Address: delegate call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r\n     * but performing a delegate call.\r\n     *\r\n     * _Available since v3.4._\r\n     */\r\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\r\n        require(isContract(target), \"Address: delegate call to non-contract\");\r\n\r\n        // solhint-disable-next-line avoid-low-level-calls\r\n        (bool success, bytes memory returndata) = target.delegatecall(data);\r\n        return _verifyCallResult(success, returndata, errorMessage);\r\n    }\r\n\r\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\r\n        if (success) {\r\n            return returndata;\r\n        } else {\r\n            // Look for revert reason and bubble it up if present\r\n            if (returndata.length > 0) {\r\n                // The easiest way to bubble the revert reason is using memory via assembly\r\n\r\n                // solhint-disable-next-line no-inline-assembly\r\n                assembly {\r\n                    let returndata_size := mload(returndata)\r\n                    revert(add(32, returndata), returndata_size)\r\n                }\r\n            } else {\r\n                revert(errorMessage);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\n\r\n// Dependency file: contracts/zeppelin/token/ERC20/SafeERC20.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n// import \"contracts/zeppelin/token/ERC20/IERC20.sol\";\r\n// import \"contracts/zeppelin/math/SafeMath.sol\";\r\n// import \"contracts/zeppelin/utils/Address.sol\";\r\n\r\n/**\r\n * @title SafeERC20\r\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\r\n * contract returns false). Tokens that return no value (and instead revert or\r\n * throw on failure) are also supported, non-reverting calls are assumed to be\r\n * successful.\r\n * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,\r\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\r\n */\r\nlibrary SafeERC20 {\r\n    using SafeMath for uint256;\r\n    using Address for address;\r\n\r\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\r\n        callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\r\n    }\r\n\r\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\r\n        callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\r\n    }\r\n\r\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\r\n        // safeApprove should only be called when setting an initial allowance,\r\n        // or when resetting it to zero. To increase and decrease it, use\r\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\r\n        // solhint-disable-next-line max-line-length\r\n        require((value == 0) || (token.allowance(address(this), spender) == 0),\r\n            \"SafeERC20: approve non-zero to non-zero allowance\"\r\n        );\r\n        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\r\n    }\r\n\r\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\r\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\r\n        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\r\n    }\r\n\r\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\r\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\r\n        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\r\n    }\r\n\r\n    /**\r\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\r\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\r\n     * @param token The token targeted by the call.\r\n     * @param data The call data (encoded using abi.encode or one of its variants).\r\n     */\r\n    function callOptionalReturn(IERC20 token, bytes memory data) private {\r\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\r\n        // we're implementing it ourselves.\r\n\r\n        // A Solidity high level call has three parts:\r\n        //  1. The target address is checked to verify it contains contract code\r\n        //  2. The call itself is made, and success asserted\r\n        //  3. The return value is decoded, which in turn checks the size of the returned data.\r\n        // solhint-disable-next-line max-line-length\r\n        require(address(token).isContract(), \"SafeERC20: call to non-contract\");\r\n\r\n        // solhint-disable-next-line avoid-low-level-calls\r\n        (bool success, bytes memory returndata) = address(token).call(data);\r\n        require(success, \"SafeERC20: low-level call failed\");\r\n\r\n        if (returndata.length > 0) { // Return data is optional\r\n            // solhint-disable-next-line max-line-length\r\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\r\n        }\r\n    }\r\n}\r\n\r\n\r\n// Dependency file: contracts/zeppelin/token/ERC777/IERC777.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n/**\r\n * @dev Interface of the ERC777Token standard as defined in the EIP.\r\n *\r\n * This contract uses the\r\n * [ERC1820 registry standard](https://eips.ethereum.org/EIPS/eip-1820) to let\r\n * token holders and recipients react to token movements by using setting implementers\r\n * for the associated interfaces in said registry. See `IERC1820Registry` and\r\n * `ERC1820Implementer`.\r\n */\r\ninterface IERC777 {\r\n    /**\r\n     * @dev Returns the name of the token.\r\n     */\r\n    function name() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the symbol of the token, usually a shorter version of the\r\n     * name.\r\n     */\r\n    function symbol() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Returns the smallest part of the token that is not divisible. This\r\n     * means all token operations (creation, movement and destruction) must have\r\n     * amounts that are a multiple of this number.\r\n     *\r\n     * For most token contracts, this value will equal 1.\r\n     */\r\n    function granularity() external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens in existence.\r\n     */\r\n    function totalSupply() external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens owned by an account (`owner`).\r\n     */\r\n    function balanceOf(address owner) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\r\n     *\r\n     * If send or receive hooks are registered for the caller and `recipient`,\r\n     * the corresponding functions will be called with `data` and empty\r\n     * `operatorData`. See `IERC777Sender` and `IERC777Recipient`.\r\n     *\r\n     * Emits a `Sent` event.\r\n     *\r\n     * Requirements\r\n     *\r\n     * - the caller must have at least `amount` tokens.\r\n     * - `recipient` cannot be the zero address.\r\n     * - if `recipient` is a contract, it must implement the `tokensReceived`\r\n     * interface.\r\n     */\r\n    function send(address recipient, uint256 amount, bytes calldata data) external;\r\n\r\n    /**\r\n     * @dev Destroys `amount` tokens from the caller's account, reducing the\r\n     * total supply.\r\n     *\r\n     * If a send hook is registered for the caller, the corresponding function\r\n     * will be called with `data` and empty `operatorData`. See `IERC777Sender`.\r\n     *\r\n     * Emits a `Burned` event.\r\n     *\r\n     * Requirements\r\n     *\r\n     * - the caller must have at least `amount` tokens.\r\n     */\r\n    function burn(uint256 amount, bytes calldata data) external;\r\n\r\n    /**\r\n     * @dev Returns true if an account is an operator of `tokenHolder`.\r\n     * Operators can send and burn tokens on behalf of their owners. All\r\n     * accounts are their own operator.\r\n     *\r\n     * See `operatorSend` and `operatorBurn`.\r\n     */\r\n    function isOperatorFor(address operator, address tokenHolder) external view returns (bool);\r\n\r\n    /**\r\n     * @dev Make an account an operator of the caller.\r\n     *\r\n     * See `isOperatorFor`.\r\n     *\r\n     * Emits an `AuthorizedOperator` event.\r\n     *\r\n     * Requirements\r\n     *\r\n     * - `operator` cannot be calling address.\r\n     */\r\n    function authorizeOperator(address operator) external;\r\n\r\n    /**\r\n     * @dev Make an account an operator of the caller.\r\n     *\r\n     * See `isOperatorFor` and `defaultOperators`.\r\n     *\r\n     * Emits a `RevokedOperator` event.\r\n     *\r\n     * Requirements\r\n     *\r\n     * - `operator` cannot be calling address.\r\n     */\r\n    function revokeOperator(address operator) external;\r\n\r\n    /**\r\n     * @dev Returns the list of default operators. These accounts are operators\r\n     * for all token holders, even if `authorizeOperator` was never called on\r\n     * them.\r\n     *\r\n     * This list is immutable, but individual holders may revoke these via\r\n     * `revokeOperator`, in which case `isOperatorFor` will return false.\r\n     */\r\n    function defaultOperators() external view returns (address[] memory);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must\r\n     * be an operator of `sender`.\r\n     *\r\n     * If send or receive hooks are registered for `sender` and `recipient`,\r\n     * the corresponding functions will be called with `data` and\r\n     * `operatorData`. See `IERC777Sender` and `IERC777Recipient`.\r\n     *\r\n     * Emits a `Sent` event.\r\n     *\r\n     * Requirements\r\n     *\r\n     * - `sender` cannot be the zero address.\r\n     * - `sender` must have at least `amount` tokens.\r\n     * - the caller must be an operator for `sender`.\r\n     * - `recipient` cannot be the zero address.\r\n     * - if `recipient` is a contract, it must implement the `tokensReceived`\r\n     * interface.\r\n     */\r\n    function operatorSend(\r\n        address sender,\r\n        address recipient,\r\n        uint256 amount,\r\n        bytes calldata data,\r\n        bytes calldata operatorData\r\n    ) external;\r\n\r\n    /**\r\n     * @dev Destoys `amount` tokens from `account`, reducing the total supply.\r\n     * The caller must be an operator of `account`.\r\n     *\r\n     * If a send hook is registered for `account`, the corresponding function\r\n     * will be called with `data` and `operatorData`. See `IERC777Sender`.\r\n     *\r\n     * Emits a `Burned` event.\r\n     *\r\n     * Requirements\r\n     *\r\n     * - `account` cannot be the zero address.\r\n     * - `account` must have at least `amount` tokens.\r\n     * - the caller must be an operator for `account`.\r\n     */\r\n    function operatorBurn(\r\n        address account,\r\n        uint256 amount,\r\n        bytes calldata data,\r\n        bytes calldata operatorData\r\n    ) external;\r\n\r\n    event Sent(\r\n        address indexed operator,\r\n        address indexed from,\r\n        address indexed to,\r\n        uint256 amount,\r\n        bytes data,\r\n        bytes operatorData\r\n    );\r\n\r\n    function decimals() external returns (uint8);\r\n\r\n    event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);\r\n\r\n    event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);\r\n\r\n    event AuthorizedOperator(address indexed operator, address indexed tokenHolder);\r\n\r\n    event RevokedOperator(address indexed operator, address indexed tokenHolder);\r\n}\r\n\r\n\r\n// Dependency file: contracts/LibEIP712.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\n// https://github.com/0xProject/0x-monorepo/blob/development/contracts/utils/contracts/src/LibEIP712.sol\r\nlibrary LibEIP712 {\r\n\r\n    // Hash of the EIP712 Domain Separator Schema\r\n    // keccak256(abi.encodePacked(\r\n    //     \"EIP712Domain(\",\r\n    //     \"string name,\",\r\n    //     \"string version,\",\r\n    //     \"uint256 chainId,\",\r\n    //     \"address verifyingContract\",\r\n    //     \")\"\r\n    // ))\r\n    bytes32 constant internal _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;\r\n\r\n    /// @dev Calculates a EIP712 domain separator.\r\n    /// @param name The EIP712 domain name.\r\n    /// @param version The EIP712 domain version.\r\n    /// @param verifyingContract The EIP712 verifying contract.\r\n    /// @return result EIP712 domain separator.\r\n    function hashEIP712Domain(\r\n        string memory name,\r\n        string memory version,\r\n        uint256 chainId,\r\n        address verifyingContract\r\n    )\r\n        internal\r\n        pure\r\n        returns (bytes32 result)\r\n    {\r\n        bytes32 schemaHash = _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH;\r\n\r\n        // Assembly for more efficient computing:\r\n        // keccak256(abi.encodePacked(\r\n        //     _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH,\r\n        //     keccak256(bytes(name)),\r\n        //     keccak256(bytes(version)),\r\n        //     chainId,\r\n        //     uint256(verifyingContract)\r\n        // ))\r\n\r\n        // solium-disable-next-line security/no-inline-assembly\r\n        assembly {\r\n            // Calculate hashes of dynamic data\r\n            let nameHash := keccak256(add(name, 32), mload(name))\r\n            let versionHash := keccak256(add(version, 32), mload(version))\r\n\r\n            // Load free memory pointer\r\n            let memPtr := mload(64)\r\n\r\n            // Store params in memory\r\n            mstore(memPtr, schemaHash)\r\n            mstore(add(memPtr, 32), nameHash)\r\n            mstore(add(memPtr, 64), versionHash)\r\n            mstore(add(memPtr, 96), chainId)\r\n            mstore(add(memPtr, 128), verifyingContract)\r\n\r\n            // Compute hash\r\n            result := keccak256(memPtr, 160)\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /// @dev Calculates EIP712 encoding for a hash struct with a given domain hash.\r\n    /// @param eip712DomainHash Hash of the domain domain separator data, computed\r\n    ///                         with getDomainHash().\r\n    /// @param hashStruct The EIP712 hash struct.\r\n    /// @return result EIP712 hash applied to the given EIP712 Domain.\r\n    function hashEIP712Message(bytes32 eip712DomainHash, bytes32 hashStruct)\r\n        internal\r\n        pure\r\n        returns (bytes32 result)\r\n    {\r\n        // Assembly for more efficient computing:\r\n        // keccak256(abi.encodePacked(\r\n        //     EIP191_HEADER,\r\n        //     EIP712_DOMAIN_HASH,\r\n        //     hashStruct\r\n        // ));\r\n\r\n        // solium-disable-next-line security/no-inline-assembly\r\n        assembly {\r\n            // Load free memory pointer\r\n            let memPtr := mload(64)\r\n\r\n            mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000)  // EIP191 header\r\n            mstore(add(memPtr, 2), eip712DomainHash)                                            // EIP712 domain hash\r\n            mstore(add(memPtr, 34), hashStruct)                                                 // Hash of struct\r\n\r\n            // Compute hash\r\n            result := keccak256(memPtr, 66)\r\n        }\r\n        return result;\r\n    }\r\n}\r\n\r\n// Dependency file: contracts/LibUtils.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\nlibrary LibUtils {\r\n\r\n    function decimalsToGranularity(uint8 decimals) internal pure returns (uint256) {\r\n        require(decimals <= 18, \"LibUtils: Decimals not <= 18\");\r\n        return uint256(10)**(18-decimals);\r\n    }\r\n\r\n    function getDecimals(address tokenToUse) internal view returns (uint8) {\r\n        //support decimals as uint256 or uint8\r\n        (bool success, bytes memory data) = tokenToUse.staticcall(abi.encodeWithSignature(\"decimals()\"));\r\n        require(success, \"LibUtils: No decimals\");\r\n        // uint<M>: enc(X) is the big-endian encoding of X,\r\n        //padded on the higher-order (left) side with zero-bytes such that the length is 32 bytes.\r\n        return uint8(abi.decode(data, (uint256)));\r\n    }\r\n\r\n    function getGranularity(address tokenToUse) internal view returns (uint256) {\r\n        //support granularity if ERC777\r\n        (bool success, bytes memory data) = tokenToUse.staticcall(abi.encodeWithSignature(\"granularity()\"));\r\n        require(success, \"LibUtils: No granularity\");\r\n\r\n        return abi.decode(data, (uint256));\r\n    }\r\n\r\n    function bytesToAddress(bytes memory bys) internal pure returns (address addr) {\r\n        // solium-disable-next-line security/no-inline-assembly\r\n        assembly {\r\n            addr := mload(add(bys,20))\r\n        }\r\n    }\r\n\r\n}\r\n\r\n\r\n// Dependency file: contracts/IBridge.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\ninterface IBridge {\r\n\r\n    struct ClaimData {\r\n        address payable to;\r\n        uint256 amount;\r\n        bytes32 blockHash;\r\n        bytes32 transactionHash;\r\n        uint32 logIndex;\r\n    }\r\n\r\n    function version() external pure returns (string memory);\r\n\r\n    function getFeePercentage() external view returns(uint);\r\n\r\n    /**\r\n     * ERC-20 tokens approve and transferFrom pattern\r\n     * See https://eips.ethereum.org/EIPS/eip-20#transferfrom\r\n     */\r\n    function receiveTokensTo(address tokenToUse, address to, uint256 amount) external;\r\n\r\n    /**\r\n     * Use network currency and cross it.\r\n     */\r\n    function depositTo(address to) external payable;\r\n\r\n    /**\r\n     * ERC-777 tokensReceived hook allows to send tokens to a contract and notify it in a single transaction\r\n     * See https://eips.ethereum.org/EIPS/eip-777#motivation for details\r\n     */\r\n    function tokensReceived (\r\n        address operator,\r\n        address from,\r\n        address to,\r\n        uint amount,\r\n        bytes calldata userData,\r\n        bytes calldata operatorData\r\n    ) external;\r\n\r\n    /**\r\n     * Accepts the transaction from the other chain that was voted and sent by the Federation contract\r\n     */\r\n    function acceptTransfer(\r\n        address _originalTokenAddress,\r\n        address payable _from,\r\n        address payable _to,\r\n        uint256 _amount,\r\n        bytes32 _blockHash,\r\n        bytes32 _transactionHash,\r\n        uint32 _logIndex\r\n    ) external;\r\n\r\n    /**\r\n     * Claims the crossed transaction using the hash, this sends the funds to the address indicated in\r\n     */\r\n    function claim(ClaimData calldata _claimData) external returns (uint256 receivedAmount);\r\n\r\n    function claimFallback(ClaimData calldata _claimData) external returns (uint256 receivedAmount);\r\n\r\n    function claimGasless(\r\n        ClaimData calldata _claimData,\r\n        address payable _relayer,\r\n        uint256 _fee,\r\n        uint256 _deadline,\r\n        uint8 _v,\r\n        bytes32 _r,\r\n        bytes32 _s\r\n    ) external returns (uint256 receivedAmount);\r\n\r\n    function getTransactionDataHash(\r\n        address _to,\r\n        uint256 _amount,\r\n        bytes32 _blockHash,\r\n        bytes32 _transactionHash,\r\n        uint32 _logIndex\r\n    ) external returns(bytes32);\r\n\r\n    event Cross(\r\n        address indexed _tokenAddress,\r\n        address indexed _from,\r\n        address indexed _to,\r\n        uint256 _amount,\r\n        bytes _userData\r\n    );\r\n    event NewSideToken(\r\n        address indexed _newSideTokenAddress,\r\n        address indexed _originalTokenAddress,\r\n        string _newSymbol,\r\n        uint256 _granularity\r\n    );\r\n    event AcceptedCrossTransfer(\r\n        bytes32 indexed _transactionHash,\r\n        address indexed _originalTokenAddress,\r\n        address indexed _to,\r\n        address  _from,\r\n        uint256 _amount,\r\n        bytes32 _blockHash,\r\n        uint256 _logIndex\r\n    );\r\n    event FeePercentageChanged(uint256 _amount);\r\n    event Claimed(\r\n        bytes32 indexed _transactionHash,\r\n        address indexed _originalTokenAddress,\r\n        address indexed _to,\r\n        address _sender,\r\n        uint256 _amount,\r\n        bytes32 _blockHash,\r\n        uint256 _logIndex,\r\n        address _reciever,\r\n        address _relayer,\r\n        uint256 _fee\r\n    );\r\n}\r\n\r\n// Dependency file: contracts/ISideToken.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\ninterface ISideToken {\r\n    function mint(address account, uint256 amount, bytes calldata userData, bytes calldata operatorData) external;\r\n}\r\n\r\n// Dependency file: contracts/ISideTokenFactory.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\n\r\ninterface ISideTokenFactory {\r\n\r\n    function createSideToken(string calldata name, string calldata symbol, uint256 granularity) external returns(address);\r\n\r\n    event SideTokenCreated(address indexed sideToken, string symbol, uint256 granularity);\r\n}\r\n\r\n// Dependency file: contracts/IAllowTokens.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\ninterface IAllowTokens {\r\n\r\n    struct Limits {\r\n        uint256 min;\r\n        uint256 max;\r\n        uint256 daily;\r\n        uint256 mediumAmount;\r\n        uint256 largeAmount;\r\n    }\r\n\r\n    struct TokenInfo {\r\n        bool allowed;\r\n        uint256 typeId;\r\n        uint256 spentToday;\r\n        uint256 lastDay;\r\n    }\r\n\r\n    struct TypeInfo {\r\n        string description;\r\n        Limits limits;\r\n    }\r\n\r\n    struct TokensAndType {\r\n        address token;\r\n        uint256 typeId;\r\n    }\r\n\r\n    function version() external pure returns (string memory);\r\n\r\n    function getInfoAndLimits(address token) external view returns (TokenInfo memory info, Limits memory limit);\r\n\r\n    function calcMaxWithdraw(address token) external view returns (uint256 maxWithdraw);\r\n\r\n    function getTypesLimits() external view returns(Limits[] memory limits);\r\n\r\n    function getTypeDescriptionsLength() external view returns(uint256);\r\n\r\n    function getTypeDescriptions() external view returns(string[] memory descriptions);\r\n\r\n    function setToken(address token, uint256 typeId) external;\r\n\r\n    function getConfirmations() external view returns (uint256 smallAmount, uint256 mediumAmount, uint256 largeAmount);\r\n\r\n    function isTokenAllowed(address token) external view returns (bool);\r\n\r\n    function updateTokenTransfer(address token, uint256 amount) external;\r\n}\r\n\r\n// Dependency file: contracts/IWrapped.sol\r\n\r\n\r\n// pragma solidity ^0.7.0;\r\n// pragma abicoder v2;\r\ninterface IWrapped {\r\n    function balanceOf(address) external returns(uint);\r\n\r\n    function deposit() external payable;\r\n\r\n    function withdraw(uint wad) external;\r\n\r\n    function totalSupply() external view returns (uint);\r\n\r\n    function approve(address guy, uint wad) external returns (bool);\r\n\r\n    function transfer(address dst, uint wad) external returns (bool);\r\n\r\n    function transferFrom(address src, address dst, uint wad)\r\n        external\r\n        returns (bool);\r\n}\r\n\r\n// Root file: contracts/Bridge.sol\r\n\r\n\r\npragma solidity ^0.7.0;\r\npragma abicoder v2;\r\n\r\n// Import base Initializable contract\r\n// import \"contracts/zeppelin/upgradable/Initializable.sol\";\r\n// Import interface and library from OpenZeppelin contracts\r\n// import \"contracts/zeppelin/upgradable/utils/ReentrancyGuard.sol\";\r\n// import \"contracts/zeppelin/upgradable/lifecycle/UpgradablePausable.sol\";\r\n// import \"contracts/zeppelin/upgradable/ownership/UpgradableOwnable.sol\";\r\n\r\n// import \"contracts/zeppelin/introspection/IERC1820Registry.sol\";\r\n// import \"contracts/zeppelin/token/ERC777/IERC777Recipient.sol\";\r\n// import \"contracts/zeppelin/token/ERC20/IERC20.sol\";\r\n// import \"contracts/zeppelin/token/ERC20/SafeERC20.sol\";\r\n// import \"contracts/zeppelin/utils/Address.sol\";\r\n// import \"contracts/zeppelin/math/SafeMath.sol\";\r\n// import \"contracts/zeppelin/token/ERC777/IERC777.sol\";\r\n\r\n// import \"contracts/LibEIP712.sol\";\r\n// import \"contracts/LibUtils.sol\";\r\n\r\n// import \"contracts/IBridge.sol\";\r\n// import \"contracts/ISideToken.sol\";\r\n// import \"contracts/ISideTokenFactory.sol\";\r\n// import \"contracts/IAllowTokens.sol\";\r\n// import \"contracts/IWrapped.sol\";\r\n\r\n\r\ncontract Bridge is Initializable, IBridge, IERC777Recipient, UpgradablePausable, UpgradableOwnable, ReentrancyGuard {\r\n    using SafeMath for uint256;\r\n    using SafeERC20 for IERC20;\r\n    using Address for address;\r\n\r\n    address constant internal NULL_ADDRESS = address(0);\r\n    bytes32 constant internal NULL_HASH = bytes32(0);\r\n    IERC1820Registry constant internal erc1820 = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);\r\n\r\n    address internal federation;\r\n    uint256 internal feePercentage;\r\n    string public symbolPrefix;\r\n    bytes32 public DOMAIN_SEPARATOR; // replaces uint256 internal _depprecatedLastDay;\r\n    uint256 internal _deprecatedSpentToday;\r\n\r\n    mapping (address => address) public mappedTokens; // OirignalToken => SideToken\r\n    mapping (address => address) public originalTokens; // SideToken => OriginalToken\r\n    mapping (address => bool) public knownTokens; // OriginalToken => true\r\n    mapping (bytes32 => bool) public claimed; // transactionDataHash => true // previously named processed\r\n    IAllowTokens public allowTokens;\r\n    ISideTokenFactory public sideTokenFactory;\r\n    //Bridge_v1 variables\r\n    bool public isUpgrading;\r\n    uint256 constant public feePercentageDivider = 10000; // Porcentage with up to 2 decimals\r\n    //Bridge_v3 variables\r\n    bytes32 constant internal _erc777Interface = keccak256(\"ERC777Token\");\r\n    IWrapped public wrappedCurrency;\r\n    mapping (bytes32 => bytes32) public transactionsDataHashes; // transactionHash => transactionDataHash\r\n    mapping (bytes32 => address) public originalTokenAddresses; // transactionHash => originalTokenAddress\r\n    mapping (bytes32 => address) public senderAddresses; // transactionHash => senderAddress\r\n\r\n    // keccak256(\"Claim(address to,uint256 amount,bytes32 transactionHash,address relayer,uint256 fee,uint256 nonce,uint256 deadline)\");\r\n    bytes32 public constant CLAIM_TYPEHASH = 0xf18ceda3f6355f78c234feba066041a50f6557bfb600201e2a71a89e2dd80433;\r\n    mapping(address => uint) public nonces;\r\n\r\n    event AllowTokensChanged(address _newAllowTokens);\r\n    event FederationChanged(address _newFederation);\r\n    event SideTokenFactoryChanged(address _newSideTokenFactory);\r\n    event Upgrading(bool _isUpgrading);\r\n    event WrappedCurrencyChanged(address _wrappedCurrency);\r\n\r\n    function initialize(\r\n        address _manager,\r\n        address _federation,\r\n        address _allowTokens,\r\n        address _sideTokenFactory,\r\n        string memory _symbolPrefix\r\n    ) public initializer {\r\n        UpgradableOwnable.initialize(_manager);\r\n        UpgradablePausable.__Pausable_init(_manager);\r\n        symbolPrefix = _symbolPrefix;\r\n        allowTokens = IAllowTokens(_allowTokens);\r\n        sideTokenFactory = ISideTokenFactory(_sideTokenFactory);\r\n        federation = _federation;\r\n        //keccak256(\"ERC777TokensRecipient\")\r\n        erc1820.setInterfaceImplementer(address(this), 0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b, address(this));\r\n        initDomainSeparator();\r\n    }\r\n\r\n    receive () external payable {\r\n        // The fallback function is needed to use WRBTC\r\n        require(_msgSender() == address(wrappedCurrency), \"Bridge: not wrappedCurrency\");\r\n    }\r\n\r\n    function version() override external pure returns (string memory) {\r\n        return \"v3\";\r\n    }\r\n\r\n    function initDomainSeparator() public {\r\n        uint chainId;\r\n        // solium-disable-next-line security/no-inline-assembly\r\n        assembly {\r\n            chainId := chainid()\r\n        }\r\n        DOMAIN_SEPARATOR = LibEIP712.hashEIP712Domain(\r\n            \"RSK Token Bridge\",\r\n            \"1\",\r\n            chainId,\r\n            address(this)\r\n        );\r\n    }\r\n\r\n    modifier whenNotUpgrading() {\r\n        require(!isUpgrading, \"Bridge: Upgrading\");\r\n        _;\r\n    }\r\n\r\n    function acceptTransfer(\r\n        address _originalTokenAddress,\r\n        address payable _from,\r\n        address payable _to,\r\n        uint256 _amount,\r\n        bytes32 _blockHash,\r\n        bytes32 _transactionHash,\r\n        uint32 _logIndex\r\n    ) external whenNotPaused nonReentrant override {\r\n        require(_msgSender() == federation, \"Bridge: Not Federation\");\r\n        require(knownTokens[_originalTokenAddress] ||\r\n            mappedTokens[_originalTokenAddress] != NULL_ADDRESS,\r\n            \"Bridge: Unknown token\"\r\n        );\r\n        require(_to != NULL_ADDRESS, \"Bridge: Null To\");\r\n        require(_amount > 0, \"Bridge: Amount 0\");\r\n        require(_blockHash != NULL_HASH, \"Bridge: Null BlockHash\");\r\n        require(_transactionHash != NULL_HASH, \"Bridge: Null TxHash\");\r\n        require(transactionsDataHashes[_transactionHash] == bytes32(0), \"Bridge: Already accepted\");\r\n\r\n        bytes32 _transactionDataHash = getTransactionDataHash(\r\n            _to,\r\n            _amount,\r\n            _blockHash,\r\n            _transactionHash,\r\n            _logIndex\r\n        );\r\n        // Do not remove, claimed also has the previously processed using the older bridge version\r\n        // https://github.com/rsksmart/tokenbridge/blob/TOKENBRIDGE-1.2.0/bridge/contracts/Bridge.sol#L41\r\n        require(!claimed[_transactionDataHash], \"Bridge: Already claimed\");\r\n\r\n        transactionsDataHashes[_transactionHash] = _transactionDataHash;\r\n        originalTokenAddresses[_transactionHash] = _originalTokenAddress;\r\n        senderAddresses[_transactionHash] = _from;\r\n\r\n        emit AcceptedCrossTransfer(\r\n            _transactionHash,\r\n            _originalTokenAddress,\r\n            _to,\r\n            _from,\r\n            _amount,\r\n            _blockHash,\r\n            _logIndex\r\n        );\r\n    }\r\n\r\n\r\n    function createSideToken(\r\n        uint256 _typeId,\r\n        address _originalTokenAddress,\r\n        uint8 _originalTokenDecimals,\r\n        string calldata _originalTokenSymbol,\r\n        string calldata _originalTokenName\r\n    ) external onlyOwner {\r\n        require(_originalTokenAddress != NULL_ADDRESS, \"Bridge: Null token\");\r\n        address sideToken = mappedTokens[_originalTokenAddress];\r\n        require(sideToken == NULL_ADDRESS, \"Bridge: Already exists\");\r\n        uint256 granularity = LibUtils.decimalsToGranularity(_originalTokenDecimals);\r\n        string memory newSymbol = string(abi.encodePacked(symbolPrefix, _originalTokenSymbol));\r\n\r\n        // Create side token\r\n        sideToken = sideTokenFactory.createSideToken(_originalTokenName, newSymbol, granularity);\r\n\r\n        mappedTokens[_originalTokenAddress] = sideToken;\r\n        originalTokens[sideToken] = _originalTokenAddress;\r\n        allowTokens.setToken(sideToken, _typeId);\r\n\r\n        emit NewSideToken(sideToken, _originalTokenAddress, newSymbol, granularity);\r\n    }\r\n\r\n    function claim(ClaimData calldata _claimData)\r\n    external override returns (uint256 receivedAmount) {\r\n\r\n        receivedAmount = _claim(\r\n            _claimData,\r\n            _claimData.to,\r\n            payable(address(0)),\r\n            0\r\n        );\r\n        return receivedAmount;\r\n    }\r\n\r\n    function claimFallback(ClaimData calldata _claimData)\r\n    external override returns (uint256 receivedAmount) {\r\n        require(_msgSender() == senderAddresses[_claimData.transactionHash],\"Bridge: invalid sender\");\r\n        receivedAmount = _claim(\r\n            _claimData,\r\n            _msgSender(),\r\n            payable(address(0)),\r\n            0\r\n        );\r\n        return receivedAmount;\r\n    }\r\n\r\n    function getDigest(\r\n        ClaimData memory _claimData,\r\n        address payable _relayer,\r\n        uint256 _fee,\r\n        uint256 _deadline\r\n    ) internal returns (bytes32) {\r\n        return LibEIP712.hashEIP712Message(\r\n            DOMAIN_SEPARATOR,\r\n            keccak256(\r\n                abi.encode(\r\n                    CLAIM_TYPEHASH,\r\n                    _claimData.to,\r\n                    _claimData.amount,\r\n                    _claimData.transactionHash,\r\n                    _relayer,\r\n                    _fee,\r\n                    nonces[_claimData.to]++,\r\n                    _deadline\r\n                )\r\n            )\r\n        );\r\n    }\r\n\r\n    // Inspired by https://github.com/dapphub/ds-dach/blob/master/src/dach.sol\r\n    function claimGasless(\r\n        ClaimData calldata _claimData,\r\n        address payable _relayer,\r\n        uint256 _fee,\r\n        uint256 _deadline,\r\n        uint8 _v,\r\n        bytes32 _r,\r\n        bytes32 _s\r\n    ) external override returns (uint256 receivedAmount) {\r\n        require(_deadline >= block.timestamp, \"Bridge: EXPIRED\");\r\n\r\n        bytes32 digest = getDigest(_claimData, _relayer, _fee, _deadline);\r\n        address recoveredAddress = ecrecover(digest, _v, _r, _s);\r\n        require(_claimData.to != address(0) && recoveredAddress == _claimData.to, \"Bridge: INVALID_SIGNATURE\");\r\n\r\n        receivedAmount = _claim(\r\n            _claimData,\r\n            _claimData.to,\r\n            _relayer,\r\n            _fee\r\n        );\r\n        return receivedAmount;\r\n    }\r\n\r\n    function _claim(\r\n        ClaimData calldata _claimData,\r\n        address payable _reciever,\r\n        address payable _relayer,\r\n        uint256 _fee\r\n    ) internal nonReentrant returns (uint256 receivedAmount) {\r\n        address originalTokenAddress = originalTokenAddresses[_claimData.transactionHash];\r\n        require(originalTokenAddress != NULL_ADDRESS, \"Bridge: Tx not crossed\");\r\n\r\n        bytes32 transactionDataHash = getTransactionDataHash(\r\n            _claimData.to,\r\n            _claimData.amount,\r\n            _claimData.blockHash,\r\n            _claimData.transactionHash,\r\n            _claimData.logIndex\r\n        );\r\n        require(transactionsDataHashes[_claimData.transactionHash] == transactionDataHash, \"Bridge: Wrong transactionDataHash\");\r\n        require(!claimed[transactionDataHash], \"Bridge: Already claimed\");\r\n\r\n        claimed[transactionDataHash] = true;\r\n        if (knownTokens[originalTokenAddress]) {\r\n            receivedAmount =_claimCrossBackToToken(\r\n                originalTokenAddress,\r\n                _reciever,\r\n                _claimData.amount,\r\n                _relayer,\r\n                _fee\r\n            );\r\n        } else {\r\n            receivedAmount =_claimCrossToSideToken(\r\n                originalTokenAddress,\r\n                _reciever,\r\n                _claimData.amount,\r\n                _relayer,\r\n                _fee\r\n            );\r\n        }\r\n        emit Claimed(\r\n            _claimData.transactionHash,\r\n            originalTokenAddress,\r\n            _claimData.to,\r\n            senderAddresses[_claimData.transactionHash],\r\n            _claimData.amount,\r\n            _claimData.blockHash,\r\n            _claimData.logIndex,\r\n            _reciever,\r\n            _relayer,\r\n            _fee\r\n        );\r\n        return receivedAmount;\r\n    }\r\n\r\n    function _claimCrossToSideToken(\r\n        address _originalTokenAddress,\r\n        address payable _receiver,\r\n        uint256 _amount,\r\n        address payable _relayer,\r\n        uint256 _fee\r\n    ) internal returns (uint256 receivedAmount) {\r\n        address sideToken = mappedTokens[_originalTokenAddress];\r\n        uint256 granularity = IERC777(sideToken).granularity();\r\n        uint256 formattedAmount = _amount.mul(granularity);\r\n        require(_fee <= formattedAmount, \"Bridge: fee too high\");\r\n        receivedAmount = formattedAmount - _fee;\r\n        ISideToken(sideToken).mint(_receiver, receivedAmount, \"\", \"\");\r\n        if(_fee > 0) {\r\n            ISideToken(sideToken).mint(_relayer, _fee, \"\", \"relayer fee\");\r\n        }\r\n        return receivedAmount;\r\n    }\r\n\r\n    function _claimCrossBackToToken(\r\n        address _originalTokenAddress,\r\n        address payable _receiver,\r\n        uint256 _amount,\r\n        address payable _relayer,\r\n        uint256 _fee\r\n    ) internal returns (uint256 receivedAmount) {\r\n        uint256 decimals = LibUtils.getDecimals(_originalTokenAddress);\r\n        //As side tokens are ERC777 they will always have 18 decimals\r\n        uint256 formattedAmount = _amount.div(uint256(10) ** (18 - decimals));\r\n        require(_fee <= formattedAmount, \"Bridge: fee too high\");\r\n        receivedAmount = formattedAmount - _fee;\r\n        if(address(wrappedCurrency) == _originalTokenAddress) {\r\n            wrappedCurrency.withdraw(formattedAmount);\r\n            _receiver.transfer(receivedAmount);\r\n            if(_fee > 0) {\r\n                _relayer.transfer(_fee);\r\n            }\r\n        } else {\r\n            IERC20(_originalTokenAddress).safeTransfer(_receiver, receivedAmount);\r\n            if(_fee > 0) {\r\n                IERC20(_originalTokenAddress).safeTransfer(_relayer, _fee);\r\n            }\r\n        }\r\n        return receivedAmount;\r\n    }\r\n\r\n    /**\r\n     * ERC-20 tokens approve and transferFrom pattern\r\n     * See https://eips.ethereum.org/EIPS/eip-20#transferfrom\r\n     */\r\n    function receiveTokensTo(address tokenToUse, address to, uint256 amount) override public {\r\n        address sender = _msgSender();\r\n        //Transfer the tokens on IERC20, they should be already Approved for the bridge Address to use them\r\n        IERC20(tokenToUse).safeTransferFrom(sender, address(this), amount);\r\n        crossTokens(tokenToUse, sender, to, amount, \"\");\r\n    }\r\n\r\n    /**\r\n     * Use network currency and cross it.\r\n     */\r\n    function depositTo(address to) override external payable {\r\n        address sender = _msgSender();\r\n        require(address(wrappedCurrency) != NULL_ADDRESS, \"Bridge: wrappedCurrency empty\");\r\n        wrappedCurrency.deposit{ value: msg.value }();\r\n        crossTokens(address(wrappedCurrency), sender, to, msg.value, \"\");\r\n    }\r\n\r\n    /**\r\n     * ERC-777 tokensReceived hook allows to send tokens to a contract and notify it in a single transaction\r\n     * See https://eips.ethereum.org/EIPS/eip-777#motivation for details\r\n     */\r\n    function tokensReceived (\r\n        address operator,\r\n        address from,\r\n        address to,\r\n        uint amount,\r\n        bytes calldata userData,\r\n        bytes calldata\r\n    ) external override(IBridge, IERC777Recipient){\r\n        //Hook from ERC777address\r\n        if(operator == address(this)) return; // Avoid loop from bridge calling to ERC77transferFrom\r\n        require(to == address(this), \"Bridge: Not to this address\");\r\n        address tokenToUse = _msgSender();\r\n        require(erc1820.getInterfaceImplementer(tokenToUse, _erc777Interface) != NULL_ADDRESS, \"Bridge: Not ERC777 token\");\r\n        require(userData.length != 0 || !from.isContract(), \"Bridge: Specify receiver address in data\");\r\n        address receiver = userData.length == 0 ? from : LibUtils.bytesToAddress(userData);\r\n        crossTokens(tokenToUse, from, receiver, amount, userData);\r\n    }\r\n\r\n    function crossTokens(address tokenToUse, address from, address to, uint256 amount, bytes memory userData)\r\n    internal whenNotUpgrading whenNotPaused nonReentrant {\r\n        knownTokens[tokenToUse] = true;\r\n        uint256 fee = amount.mul(feePercentage).div(feePercentageDivider);\r\n        uint256 amountMinusFees = amount.sub(fee);\r\n        uint8 decimals = LibUtils.getDecimals(tokenToUse);\r\n        uint formattedAmount = amount;\r\n        if(decimals != 18) {\r\n            formattedAmount = amount.mul(uint256(10)**(18-decimals));\r\n        }\r\n        // We consider the amount before fees converted to 18 decimals to check the limits\r\n        // updateTokenTransfer revert if token not allowed\r\n        allowTokens.updateTokenTransfer(tokenToUse, formattedAmount);\r\n        address originalTokenAddress = tokenToUse;\r\n        if (originalTokens[tokenToUse] != NULL_ADDRESS) {\r\n            //Side Token Crossing\r\n            originalTokenAddress = originalTokens[tokenToUse];\r\n            uint256 granularity = LibUtils.getGranularity(tokenToUse);\r\n            uint256 modulo = amountMinusFees.mod(granularity);\r\n            fee = fee.add(modulo);\r\n            amountMinusFees = amountMinusFees.sub(modulo);\r\n            IERC777(tokenToUse).burn(amountMinusFees, userData);\r\n        }\r\n\r\n        emit Cross(\r\n            originalTokenAddress,\r\n            from,\r\n            to,\r\n            amountMinusFees,\r\n            userData\r\n        );\r\n\r\n        if (fee > 0) {\r\n            //Send the payment to the MultiSig of the Federation\r\n            IERC20(tokenToUse).safeTransfer(owner(), fee);\r\n        }\r\n    }\r\n\r\n    function getTransactionDataHash(\r\n        address _to,\r\n        uint256 _amount,\r\n        bytes32 _blockHash,\r\n        bytes32 _transactionHash,\r\n        uint32 _logIndex\r\n    )\r\n        public pure override returns(bytes32)\r\n    {\r\n        return keccak256(abi.encodePacked(_blockHash, _transactionHash, _to, _amount, _logIndex));\r\n    }\r\n\r\n    function setFeePercentage(uint amount) external onlyOwner {\r\n        require(amount < (feePercentageDivider/10), \"Bridge: bigger than 10%\");\r\n        feePercentage = amount;\r\n        emit FeePercentageChanged(feePercentage);\r\n    }\r\n\r\n    function getFeePercentage() external view override returns(uint) {\r\n        return feePercentage;\r\n    }\r\n\r\n    function changeFederation(address newFederation) external onlyOwner {\r\n        require(newFederation != NULL_ADDRESS, \"Bridge: Federation is empty\");\r\n        federation = newFederation;\r\n        emit FederationChanged(federation);\r\n    }\r\n\r\n\r\n    function changeAllowTokens(address newAllowTokens) external onlyOwner {\r\n        require(newAllowTokens != NULL_ADDRESS, \"Bridge: AllowTokens is empty\");\r\n        allowTokens = IAllowTokens(newAllowTokens);\r\n        emit AllowTokensChanged(newAllowTokens);\r\n    }\r\n\r\n    function getFederation() external view returns(address) {\r\n        return federation;\r\n    }\r\n\r\n    function changeSideTokenFactory(address newSideTokenFactory) external onlyOwner {\r\n        require(newSideTokenFactory != NULL_ADDRESS, \"Bridge: SideTokenFactory is empty\");\r\n        sideTokenFactory = ISideTokenFactory(newSideTokenFactory);\r\n        emit SideTokenFactoryChanged(newSideTokenFactory);\r\n    }\r\n\r\n    function setUpgrading(bool _isUpgrading) external onlyOwner {\r\n        isUpgrading = _isUpgrading;\r\n        emit Upgrading(isUpgrading);\r\n    }\r\n\r\n    function setWrappedCurrency(address _wrappedCurrency) external onlyOwner {\r\n        require(_wrappedCurrency != NULL_ADDRESS, \"Bridge: wrapp is empty\");\r\n        wrappedCurrency = IWrapped(_wrappedCurrency);\r\n        emit WrappedCurrencyChanged(_wrappedCurrency);\r\n    }\r\n\r\n    function hasCrossed(bytes32 transactionHash) public view returns (bool) {\r\n        return transactionsDataHashes[transactionHash] != bytes32(0);\r\n    }\r\n\r\n    function hasBeenClaimed(bytes32 transactionHash) public view returns (bool) {\r\n        return claimed[transactionsDataHashes[transactionHash]];\r\n    }\r\n\r\n}","deployed_bytecode":"0x6080604052600436106103025760003560e01c806382dc1ec411610190578063b86f60d2116100dc578063e6ede14d11610095578063eb16136f1161006f578063eb16136f146108a5578063f2fde38b146108c5578063f74032f0146108e5578063fa0caa16146109055761034c565b8063e6ede14d1461085b578063e6fc77441461087b578063ea217091146108905761034c565b8063b86f60d2146107b1578063c4d66de8146107c6578063ca07140c146107e6578063cc3c0f0614610806578063d12e825d14610826578063da6770371461083b5761034c565b8063adc5fb6411610149578063b0e1268e11610123578063b0e1268e14610754578063b50277bb14610769578063b760faf914610789578063b79472621461079c5761034c565b8063adc5fb64146106f4578063ae06c1b714610714578063afad80ac146107345761034c565b806382dc1ec4146106605780638456cb59146106805780638da5cb5b146106955780638f32d59b146106aa578063916dc59d146106bf578063a53d6e6e146106df5761034c565b806346fbf68e1161024f5780636a86319111610208578063715018a6116101e2578063715018a6146105f65780637813bea21461060b5780637ecebe001461062b5780638129fc1c1461064b5761034c565b80636a863191146105ac5780636b0509b1146105cc5780636ef8d66d146105e15761034c565b806346fbf68e146105005780634beea5061461052057806354fd4d501461054057806359a8a867146105625780635c975abb146105775780635d4471291461058c5761034c565b80632fb3b361116102bc57806337e761091161029657806337e76109146104715780633cf3058b1461049e5780633f4ba83a146104cb57806342cdb2c6146104e05761034c565b80632fb3b3611461041c5780633500c1dc1461043c5780633644e5151461045c5761034c565b806223de2914610351578063026976191461037157806307c8f7b0146103a757806311efbf61146103c757806320e3bb00146103dc5780632f3cca4e146103fc5761034c565b3661034c576041546001600160a01b031661031b610925565b6001600160a01b03161461034a5760405162461bcd60e51b815260040161034190613e67565b60405180910390fd5b005b600080fd5b34801561035d57600080fd5b5061034a61036c3660046130ee565b610929565b34801561037d57600080fd5b5061039161038c366004613265565b610b20565b60405161039e91906136c1565b60405180910390f35b3480156103b357600080fd5b5061034a6103c236600461322d565b610b32565b3480156103d357600080fd5b50610391610bb0565b3480156103e857600080fd5b5061034a6103f7366004613396565b610bb6565b34801561040857600080fd5b5061034a610417366004612f6c565b610df1565b34801561042857600080fd5b5061034a61043736600461301a565b610e7a565b34801561044857600080fd5b5061034a610457366004612f6c565b610fea565b34801561046857600080fd5b5061039161107f565b34801561047d57600080fd5b5061049161048c366004613265565b611085565b60405161039e91906136b6565b3480156104aa57600080fd5b506104be6104b9366004613265565b6110aa565b60405161039e919061354d565b3480156104d757600080fd5b5061034a6110c5565b3480156104ec57600080fd5b5061034a6104fb366004612f6c565b611158565b34801561050c57600080fd5b5061049161051b366004612f6c565b6111eb565b34801561052c57600080fd5b5061039161053b366004613298565b6111fe565b34801561054c57600080fd5b50610555611318565b60405161039e919061377d565b34801561056e57600080fd5b50610555611334565b34801561058357600080fd5b506104916113c2565b34801561059857600080fd5b506104916105a7366004612f6c565b6113cb565b3480156105b857600080fd5b5061034a6105c7366004612fa4565b6113e0565b3480156105d857600080fd5b50610391611644565b3480156105ed57600080fd5b5061034a611668565b34801561060257600080fd5b5061034a61167a565b34801561061757600080fd5b5061034a61062636600461319c565b6116ee565b34801561063757600080fd5b50610391610646366004612f6c565b611731565b34801561065757600080fd5b5061034a611743565b34801561066c57600080fd5b5061034a61067b366004612f6c565b6117bd565b34801561068c57600080fd5b5061034a6117ed565b3480156106a157600080fd5b506104be61186d565b3480156106b657600080fd5b50610491611881565b3480156106cb57600080fd5b5061034a6106da366004612f6c565b6118ac565b3480156106eb57600080fd5b506104be611941565b34801561070057600080fd5b5061039161070f36600461327d565b611950565b34801561072057600080fd5b5061034a61072f366004613265565b6119af565b34801561074057600080fd5b5061039161074f3660046131dc565b611a29565b34801561076057600080fd5b506104be611a65565b34801561077557600080fd5b5061039161078436600461327d565b611a74565b61034a610797366004612f6c565b611a87565b3480156107a857600080fd5b50610491611b56565b3480156107bd57600080fd5b506104be611b66565b3480156107d257600080fd5b5061034a6107e1366004612f6c565b611b75565b3480156107f257600080fd5b506104be610801366004613265565b611c40565b34801561081257600080fd5b50610491610821366004613265565b611c5b565b34801561083257600080fd5b5061034a611c70565b34801561084757600080fd5b50610491610856366004613265565b611cc8565b34801561086757600080fd5b506104be610876366004612f6c565b611cdc565b34801561088757600080fd5b50610391611cf7565b34801561089c57600080fd5b506104be611cfd565b3480156108b157600080fd5b5061034a6108c0366004612f6c565b611d0c565b3480156108d157600080fd5b5061034a6108e0366004612f6c565b611d97565b3480156108f157600080fd5b506104be610900366004612f6c565b611dc4565b34801561091157600080fd5b5061034a610920366004612f6c565b611ddf565b3390565b6001600160a01b03881630141561093f57610b16565b6001600160a01b03861630146109675760405162461bcd60e51b815260040161034190613b3b565b6000610971610925565b60405163555ddc6560e11b8152909150600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca906109d09085907fac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce217705490600401613655565b60206040518083038186803b1580156109e857600080fd5b505afa1580156109fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a209190612f88565b6001600160a01b03161415610a475760405162461bcd60e51b815260040161034190613f3c565b83151580610a645750610a62886001600160a01b0316611e7a565b155b610a805760405162461bcd60e51b815260040161034190613ba2565b60008415610acc57610ac786868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611eb692505050565b610ace565b885b9050610b13828a838a8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ebd92505050565b50505b5050505050505050565b60426020526000908152604090205481565b610b3a611881565b610b565760405162461bcd60e51b815260040161034190613db9565b6040805460ff60a01b1916600160a01b83151581029190911780835591517f983e436223c000a441c2443b394ca5fb4669a513fe86dc1dd44494047b514ad992610ba59260ff910416906136b6565b60405180910390a150565b60375490565b610bbe611881565b610bda5760405162461bcd60e51b815260040161034190613db9565b6001600160a01b038616610c005760405162461bcd60e51b815260040161034190613d8d565b6001600160a01b038087166000908152603b6020526040902054168015610c395760405162461bcd60e51b81526004016103419061405d565b6000610c4487612170565b9050600060388787604051602001610c5e939291906134d4565b60408051601f1981840301815282825290546326d9e96360e01b83529092506001600160a01b0316906326d9e96390610ca190889088908690889060040161372e565b602060405180830381600087803b158015610cbb57600080fd5b505af1158015610ccf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf39190612f88565b6001600160a01b03808b166000818152603b6020908152604080832080548688166001600160a01b03199182168117909255908452603c909252918290208054909116909217909155603f5490516378bf2b5360e01b815292955016906378bf2b5390610d669086908e90600401613655565b600060405180830381600087803b158015610d8057600080fd5b505af1158015610d94573d6000803e3d6000fd5b50505050886001600160a01b0316836001600160a01b03167f2ef93c4e96a4ef0b19497ff60c9e7360a8734f3d2cd27ae5318e43851734d17f8385604051610ddd929190613790565b60405180910390a350505050505050505050565b600054610100900460ff1680610e0a575060005460ff16155b610e265760405162461bcd60e51b8152600401610341906139eb565b600054610100900460ff16158015610e51576000805460ff1961ff0019909116610100171660011790555b610e5a82611d0c565b6034805460ff191690558015610e76576000805461ff00191690555b5050565b600054610100900460ff1680610e93575060005460ff16155b610eaf5760405162461bcd60e51b8152600401610341906139eb565b600054610100900460ff16158015610eda576000805460ff1961ff0019909116610100171660011790555b610ee386611b75565b610eec86610df1565b8151610eff906038906020850190612e48565b50603f80546001600160a01b038087166001600160a01b031992831617909255604080548684169083161781556036805493891693909216929092179055516329965a1d60e01b8152731820a4b7618bde71dce8cdc73aab6c95905fad24906329965a1d90610f969030907fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b908290600401613561565b600060405180830381600087803b158015610fb057600080fd5b505af1158015610fc4573d6000803e3d6000fd5b50505050610fd0611c70565b8015610fe2576000805461ff00191690555b505050505050565b610ff2611881565b61100e5760405162461bcd60e51b815260040161034190613db9565b6001600160a01b0381166110345760405162461bcd60e51b815260040161034190613adc565b604180546001600160a01b0319166001600160a01b0383161790556040517f0966c958966f6fac9ff807af074f8117eb2e9ce2b76390db7a158e9bdeb2485c90610ba590839061354d565b60395481565b6000818152604260209081526040808320548352603e90915290205460ff165b919050565b6044602052600090815260409020546001600160a01b031681565b6110d061051b610925565b6110ec5760405162461bcd60e51b815260040161034190613a33565b60345460ff1661110e5760405162461bcd60e51b8152600401610341906137f7565b6034805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611141610925565b60405161114e919061354d565b60405180910390a1565b611160611881565b61117c5760405162461bcd60e51b815260040161034190613db9565b6001600160a01b0381166111a25760405162461bcd60e51b815260040161034190613cd4565b604080546001600160a01b0319166001600160a01b038316178155517f619936bc6e3618d0b8dc69bcc70134fe9d88f9967f3a8b8304e318369252162590610ba590839061354d565b60006111f86033836121a3565b92915050565b6000428510156112205760405162461bcd60e51b815260040161034190613cab565b600061123c611234368b90038b018b613308565b8989896121eb565b90506000600182878787604051600081526020016040526040516112639493929190613710565b6020604051602081039080840390855afa158015611285573d6000803e3d6000fd5b5050604051601f1901519150600090506112a260208c018c612f6c565b6001600160a01b0316141580156112d657506112c160208b018b612f6c565b6001600160a01b0316816001600160a01b0316145b6112f25760405162461bcd60e51b815260040161034190613a7b565b61130a8a6113036020820182612f6c565b8b8b612280565b9a9950505050505050505050565b604080518082019091526002815261763360f01b602082015290565b6038805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156113ba5780601f1061138f576101008083540402835291602001916113ba565b820191906000526020600020905b81548152906001019060200180831161139d57829003601f168201915b505050505081565b60345460ff1690565b603d6020526000908152604090205460ff1681565b60345460ff16156114035760405162461bcd60e51b815260040161034190613c4a565b60358054600101908190556036546001600160a01b0316611422610925565b6001600160a01b0316146114485760405162461bcd60e51b815260040161034190613b72565b6001600160a01b0388166000908152603d602052604090205460ff168061148857506001600160a01b038881166000908152603b60205260409020541615155b6114a45760405162461bcd60e51b815260040161034190613b0c565b6001600160a01b0386166114ca5760405162461bcd60e51b815260040161034190613c21565b600085116114ea5760405162461bcd60e51b815260040161034190613ab2565b836115075760405162461bcd60e51b815260040161034190613ed5565b826115245760405162461bcd60e51b815260040161034190613954565b600083815260426020526040902054156115505760405162461bcd60e51b815260040161034190613e9e565b600061155f8787878787611a29565b6000818152603e602052604090205490915060ff16156115915760405162461bcd60e51b815260040161034190613e30565b60008481526042602090815260408083208490556043825280832080546001600160a01b03199081166001600160a01b038f811691821790935560449094529382902080549094168c821617909355519189169186907f2858b8803acb87882fd2de49ce7572ae3e741fb8073cbe772fa50ce00bdfba229061161a908d908c908c908b90613584565b60405180910390a4506035548114610b165760405162461bcd60e51b8152600401610341906137b2565b7ff18ceda3f6355f78c234feba066041a50f6557bfb600201e2a71a89e2dd8043381565b611678611673610925565b612499565b565b611682611881565b61169e5760405162461bcd60e51b815260040161034190613db9565b60345460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a360348054610100600160a81b0319169055565b60006116f8610925565b905061170f6001600160a01b0385168230856124db565b61172b8482858560405180602001604052806000815250611ebd565b50505050565b60456020526000908152604090205481565b600054610100900460ff168061175c575060005460ff16155b6117785760405162461bcd60e51b8152600401610341906139eb565b600054610100900460ff161580156117a3576000805460ff1961ff0019909116610100171660011790555b600160355580156117ba576000805461ff00191690555b50565b6117c861051b610925565b6117e45760405162461bcd60e51b815260040161034190613a33565b6117ba81612533565b6117f861051b610925565b6118145760405162461bcd60e51b815260040161034190613a33565b60345460ff16156118375760405162461bcd60e51b815260040161034190613c4a565b6034805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611141610925565b60345461010090046001600160a01b031690565b60345460009061010090046001600160a01b031661189d610925565b6001600160a01b031614905090565b6118b4611881565b6118d05760405162461bcd60e51b815260040161034190613db9565b6001600160a01b0381166118f65760405162461bcd60e51b815260040161034190613f05565b603f80546001600160a01b0319166001600160a01b0383161790556040517f5f2c1fe803fd576d8af05ea156011cc9cc8c025bda24c1e85772fc05a0b3f1e390610ba590839061354d565b603f546001600160a01b031681565b60608101356000908152604460205260408120546001600160a01b0316611975610925565b6001600160a01b03161461199b5760405162461bcd60e51b815260040161034190613924565b6111f8826119a7610925565b600080612280565b6119b7611881565b6119d35760405162461bcd60e51b815260040161034190613db9565b6103e881106119f45760405162461bcd60e51b81526004016103419061408d565b60378190556040517f97e97c577f03bda90e2c9739011ec065ed5fbfb36ae217d20bb0d9be95e160cd90610ba59083906136c1565b60008383878785604051602001611a44959493929190613476565b60405160208183030381529060405280519060200120905095945050505050565b6041546001600160a01b031681565b60006111f8826119a76020820182612f6c565b6000611a91610925565b6041549091506001600160a01b0316611abc5760405162461bcd60e51b815260040161034190613c74565b604160009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611b0c57600080fd5b505af1158015611b20573d6000803e3d6000fd5b5050505050610e76604160009054906101000a90046001600160a01b031682843460405180602001604052806000815250611ebd565b604054600160a01b900460ff1681565b6040546001600160a01b031681565b600054610100900460ff1680611b8e575060005460ff16155b611baa5760405162461bcd60e51b8152600401610341906139eb565b600054610100900460ff16158015611bd5576000805460ff1961ff0019909116610100171660011790555b60348054610100600160a81b0319166101006001600160a01b0385811682029290921792839055604051920416906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015610e76576000805461ff00191690555050565b6043602052600090815260409020546001600160a01b031681565b603e6020526000908152604090205460ff1681565b6000469050611cc26040518060400160405280601081526020016f52534b20546f6b656e2042726964676560801b815250604051806040016040528060018152602001603160f81b8152508330612575565b60395550565b600090815260426020526040902054151590565b603b602052600090815260409020546001600160a01b031681565b61271081565b6036546001600160a01b031690565b600054610100900460ff1680611d25575060005460ff16155b611d415760405162461bcd60e51b8152600401610341906139eb565b600054610100900460ff16158015611d6c576000805460ff1961ff0019909116610100171660011790555b611d75826111eb565b611d8257611d8282612533565b8015610e76576000805461ff00191690555050565b611d9f611881565b611dbb5760405162461bcd60e51b815260040161034190613db9565b6117ba816125cc565b603c602052600090815260409020546001600160a01b031681565b611de7611881565b611e035760405162461bcd60e51b815260040161034190613db9565b6001600160a01b038116611e295760405162461bcd60e51b81526004016103419061388b565b603680546001600160a01b0319166001600160a01b0383811691909117918290556040517f4a41a4d11aaf0c0c9e4311ac1d68b2b0134556da594779a2a35b0ddf7cd1eafb92610ba592169061354d565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611eae57508115155b949350505050565b6014015190565b604054600160a01b900460ff1615611ee75760405162461bcd60e51b8152600401610341906138f9565b60345460ff1615611f0a5760405162461bcd60e51b815260040161034190613c4a565b603580546001908101918290556001600160a01b0387166000908152603d60205260408120805460ff1916909217909155603754611f579061271090611f51908790612659565b9061269a565b90506000611f6585836126dc565b90506000611f728961271e565b905085601260ff831614611f9757611f948760ff601285900316600a0a612659565b90505b603f54604051638c34bc5560e01b81526001600160a01b0390911690638c34bc5590611fc9908d908590600401613655565b600060405180830381600087803b158015611fe357600080fd5b505af1158015611ff7573d6000803e3d6000fd5b5050506001600160a01b03808c166000908152603c60205260409020548c925016156120d157506001600160a01b03808b166000908152603c6020526040812054909116906120458c6127da565b905060006120538683612882565b905061205f87826128c4565b965061206b86826126dc565b60405163fe9d930360e01b81529096506001600160a01b038e169063fe9d93039061209c9089908d9060040161413c565b600060405180830381600087803b1580156120b657600080fd5b505af11580156120ca573d6000803e3d6000fd5b5050505050505b886001600160a01b03168a6001600160a01b0316826001600160a01b03167f1e90de9ae4d02420648a650f45f089a1be18fbca324092544ea626f9833212b0878b60405161212092919061413c565b60405180910390a4841561214a5761214a61213961186d565b6001600160a01b038d1690876128e9565b50505050506035548114610fe25760405162461bcd60e51b8152600401610341906137b2565b600060128260ff1611156121965760405162461bcd60e51b815260040161034190613d15565b5060120360ff16600a0a90565b60006001600160a01b0382166121cb5760405162461bcd60e51b815260040161034190613dee565b506001600160a01b03166000908152602091909152604090205460ff1690565b603954845160208087015160608801516001600160a01b03841660009081526045845260408082208054600181019091559051919661227796909561225c957ff18ceda3f6355f78c234feba066041a50f6557bfb600201e2a71a89e2dd8043395929490938d928d928d91016136ca565b6040516020818303038152906040528051906020012061290d565b95945050505050565b603580546001019081905560608501356000908152604360205260408120549091906001600160a01b0316806122c85760405162461bcd60e51b815260040161034190613f73565b60006122f96122da60208a018a612f6c565b60208a013560408b013560608c013561074f60a08e0160808f01613430565b6060890135600090815260426020526040902054909150811461232e5760405162461bcd60e51b8152600401610341906140fb565b6000818152603e602052604090205460ff161561235d5760405162461bcd60e51b815260040161034190613e30565b6000818152603e60209081526040808320805460ff191660011790556001600160a01b0385168352603d90915290205460ff16156123ad576123a682888a60200135898961292c565b93506123c1565b6123be82888a602001358989612aa2565b93505b6123ce6020890189612f6c565b6001600160a01b0316826001600160a01b031689606001357f42b1cb6263e8da47edf0583516eda1de16f729d26282f5791dc5b7af1010e925604460008d60600135815260200190815260200160002060009054906101000a90046001600160a01b03168c602001358d604001358e608001602081019061244f9190613430565b8e8e8e604051612465979695949392919061366e565b60405180910390a4505060355481146124905760405162461bcd60e51b8152600401610341906137b2565b50949350505050565b6124a4603382612c39565b6040516001600160a01b038216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b61172b846323b872dd60e01b8585856040516024016124fc93929190613631565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612c81565b61253e603382612d65565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b6001600160a01b0381166125f25760405162461bcd60e51b815260040161034190613fd1565b6034546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600082612668575060006111f8565b8282028284828161267557fe5b04146126935760405162461bcd60e51b815260040161034190613d4c565b9392505050565b600061269383836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612db1565b600061269383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612de8565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b1790529051600091829182916001600160a01b0386169161276491906134b8565b600060405180830381855afa9150503d806000811461279f576040519150601f19603f3d011682016040523d82523d6000602084013e6127a4565b606091505b5091509150816127c65760405162461bcd60e51b81526004016103419061385c565b80806020019051810190611eae919061337e565b60408051600481526024810182526020810180516001600160e01b031663556f0dc760e01b1790529051600091829182916001600160a01b0386169161282091906134b8565b600060405180830381855afa9150503d806000811461285b576040519150601f19603f3d011682016040523d82523d6000602084013e612860565b606091505b5091509150816127c65760405162461bcd60e51b815260040161034190613bea565b600061269383836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815250612e14565b6000828201838110156126935760405162461bcd60e51b8152600401610341906138c2565b6129088363a9059cbb60e01b84846040516024016124fc929190613655565b505050565b60405161190160f01b8152600281019290925260228201526042902090565b6000806129388761271e565b60ff1690506000612950866012849003600a0a61269a565b9050808411156129725760405162461bcd60e51b815260040161034190613fa3565b60415484820393506001600160a01b0389811691161415612a6957604154604051632e1a7d4d60e01b81526001600160a01b0390911690632e1a7d4d906129bd9084906004016136c1565b600060405180830381600087803b1580156129d757600080fd5b505af11580156129eb573d6000803e3d6000fd5b50506040516001600160a01b038a16925085156108fc02915085906000818181858888f19350505050158015612a25573d6000803e3d6000fd5b508315612a64576040516001600160a01b0386169085156108fc029086906000818181858888f19350505050158015612a62573d6000803e3d6000fd5b505b612a97565b612a7d6001600160a01b03891688856128e9565b8315612a9757612a976001600160a01b03891686866128e9565b505095945050505050565b6001600160a01b038086166000908152603b6020908152604080832054815163556f0dc760e01b81529151939416928492849263556f0dc79260048083019392829003018186803b158015612af657600080fd5b505afa158015612b0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2e919061337e565b90506000612b3c8783612659565b905080851115612b5e5760405162461bcd60e51b815260040161034190613fa3565b604051630dcdc7dd60e41b815285820394506001600160a01b0384169063dcdc7dd090612b91908b9088906004016135fb565b600060405180830381600087803b158015612bab57600080fd5b505af1158015612bbf573d6000803e3d6000fd5b505050506000851115612c2d57604051630dcdc7dd60e41b81526001600160a01b0384169063dcdc7dd090612bfa90899089906004016135b0565b600060405180830381600087803b158015612c1457600080fd5b505af1158015612c28573d6000803e3d6000fd5b505050505b50505095945050505050565b612c4382826121a3565b612c5f5760405162461bcd60e51b815260040161034190613981565b6001600160a01b0316600090815260209190915260409020805460ff19169055565b612c93826001600160a01b0316611e7a565b612caf5760405162461bcd60e51b8152600401610341906140c4565b600080836001600160a01b031683604051612cca91906134b8565b6000604051808303816000865af19150503d8060008114612d07576040519150601f19603f3d011682016040523d82523d6000602084013e612d0c565b606091505b509150915081612d2e5760405162461bcd60e51b8152600401610341906139b6565b80511561172b5780806020019051810190612d499190613249565b61172b5760405162461bcd60e51b815260040161034190614013565b612d6f82826121a3565b15612d8c5760405162461bcd60e51b815260040161034190613825565b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b60008183612dd25760405162461bcd60e51b8152600401610341919061377d565b506000838581612dde57fe5b0495945050505050565b60008184841115612e0c5760405162461bcd60e51b8152600401610341919061377d565b505050900390565b60008183612e355760405162461bcd60e51b8152600401610341919061377d565b50828481612e3f57fe5b06949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282612e7e5760008555612ec4565b82601f10612e9757805160ff1916838001178555612ec4565b82800160010185558215612ec4579182015b82811115612ec4578251825591602001919060010190612ea9565b50612ed0929150612ed4565b5090565b5b80821115612ed05760008155600101612ed5565b60008083601f840112612efa578182fd5b50813567ffffffffffffffff811115612f11578182fd5b602083019150836020828501011115612f2957600080fd5b9250929050565b600060a08284031215612f41578081fd5b50919050565b803563ffffffff811681146110a557600080fd5b803560ff811681146110a557600080fd5b600060208284031215612f7d578081fd5b8135612693816141a5565b600060208284031215612f99578081fd5b8151612693816141a5565b600080600080600080600060e0888a031215612fbe578283fd5b8735612fc9816141a5565b96506020880135612fd9816141a5565b95506040880135612fe9816141a5565b9450606088013593506080880135925060a0880135915061300c60c08901612f47565b905092959891949750929550565b600080600080600060a08688031215613031578081fd5b853561303c816141a5565b945060208681013561304d816141a5565b9450604087013561305d816141a5565b9350606087013561306d816141a5565b9250608087013567ffffffffffffffff80821115613089578384fd5b818901915089601f83011261309c578384fd5b8135818111156130a857fe5b6130ba601f8201601f19168501614155565b91508082528a848285010111156130cf578485fd5b8084840185840137810190920192909252949793965091945092919050565b60008060008060008060008060c0898b031215613109578081fd5b8835613114816141a5565b97506020890135613124816141a5565b96506040890135613134816141a5565b955060608901359450608089013567ffffffffffffffff80821115613157578283fd5b6131638c838d01612ee9565b909650945060a08b013591508082111561317b578283fd5b506131888b828c01612ee9565b999c989b5096995094979396929594505050565b6000806000606084860312156131b0578081fd5b83356131bb816141a5565b925060208401356131cb816141a5565b929592945050506040919091013590565b600080600080600060a086880312156131f3578283fd5b85356131fe816141a5565b945060208601359350604086013592506060860135915061322160808701612f47565b90509295509295909350565b60006020828403121561323e578081fd5b8135612693816141ba565b60006020828403121561325a578081fd5b8151612693816141ba565b600060208284031215613276578081fd5b5035919050565b600060a0828403121561328e578081fd5b6126938383612f30565b6000806000806000806000610160888a0312156132b3578081fd5b6132bd8989612f30565b965060a08801356132cd816141a5565b955060c0880135945060e088013593506132ea6101008901612f5b565b92506101208801359150610140880135905092959891949750929550565b600060a08284031215613319578081fd5b60405160a0810181811067ffffffffffffffff8211171561333657fe5b6040528235613344816141a5565b8082525060208301356020820152604083013560408201526060830135606082015261337260808401612f47565b60808201529392505050565b60006020828403121561338f578081fd5b5051919050565b600080600080600080600060a0888a0312156133b0578081fd5b8735965060208801356133c2816141a5565b95506133d060408901612f5b565b9450606088013567ffffffffffffffff808211156133ec578283fd5b6133f88b838c01612ee9565b909650945060808a0135915080821115613410578283fd5b5061341d8a828b01612ee9565b989b979a50959850939692959293505050565b600060208284031215613441578081fd5b61269382612f47565b60008151808452613462816020860160208601614179565b601f01601f19169290920160200192915050565b948552602085019390935260609190911b6bffffffffffffffffffffffff19166040840152605483015260e01b6001600160e01b031916607482015260780190565b600082516134ca818460208701614179565b9190910192915050565b60008085546001808216600081146134f3576001811461350a57613539565b60ff198316865260028304607f1686019350613539565b600283048986526020808720875b838110156135315781548a820152908501908201613518565b505050860193505b505050838582379092019182525092915050565b6001600160a01b0391909116815260200190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039490941684526020840192909252604083015263ffffffff16606082015260800190565b6001600160a01b03929092168252602082015260806040820181905260009082015260a060608201819052600b908201526a72656c617965722066656560a81b60c082015260e00190565b6001600160a01b039290921682526020820152608060408201819052600090820181905260a06060830181905282015260c00190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0397881681526020810196909652604086019490945263ffffffff9290921660608501528416608084015290921660a082015260c081019190915260e00190565b901515815260200190565b90815260200190565b9788526001600160a01b039687166020890152604088019590955260608701939093529316608085015260a084019290925260c083019190915260e08201526101000190565b93845260ff9290921660208401526040830152606082015260800190565b600060608252846060830152848660808401378060808684010152601f19601f8601168201608083820301602084015261376b608082018661344a565b91505082604083015295945050505050565b600060208252612693602083018461344a565b6000604082526137a3604083018561344a565b90508260208301529392505050565b60208082526025908201527f5265656e7472616e637947756172643a206e6f207265656e7472616e7420616c6040820152641b1bddd95960da1b606082015260800190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b6020808252601f908201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604082015260600190565b6020808252601590820152744c69625574696c733a204e6f20646563696d616c7360581b604082015260600190565b6020808252601b908201527f4272696467653a2046656465726174696f6e20697320656d7074790000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601190820152704272696467653a20557067726164696e6760781b604082015260600190565b602080825260169082015275213934b233b29d1034b73b30b634b21039b2b73232b960511b604082015260600190565b602080825260139082015272084e4d2c8ceca74409cead8d840a8f090c2e6d606b1b604082015260600190565b6020808252818101527f526f6c65733a206163636f756e7420646f65736e2774206861766520726f6c65604082015260600190565b6020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b60208082526028908201527f436f6e747261637420696e7374616e636520697320616c726561647920696e696040820152671d1a585b1a5e995960c21b606082015260800190565b60208082526028908201527f506175736572526f6c653a2063616c6c657220646f65736e277420686176652060408201526774686520726f6c6560c01b606082015260800190565b60208082526019908201527f4272696467653a20494e56414c49445f5349474e415455524500000000000000604082015260600190565b60208082526010908201526f04272696467653a20416d6f756e7420360841b604082015260600190565b6020808252601690820152754272696467653a20777261707020697320656d70747960501b604082015260600190565b602080825260159082015274213934b233b29d102ab735b737bbb7103a37b5b2b760591b604082015260600190565b6020808252601b908201527f4272696467653a204e6f7420746f207468697320616464726573730000000000604082015260600190565b602080825260169082015275213934b233b29d102737ba102332b232b930ba34b7b760511b604082015260600190565b60208082526028908201527f4272696467653a2053706563696679207265636569766572206164647265737360408201526720696e206461746160c01b606082015260800190565b60208082526018908201527f4c69625574696c733a204e6f206772616e756c61726974790000000000000000604082015260600190565b6020808252600f908201526e4272696467653a204e756c6c20546f60881b604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601d908201527f4272696467653a207772617070656443757272656e637920656d707479000000604082015260600190565b6020808252600f908201526e109c9a5919d94e8811561412549151608a1b604082015260600190565b60208082526021908201527f4272696467653a2053696465546f6b656e466163746f727920697320656d70746040820152607960f81b606082015260800190565b6020808252601c908201527f4c69625574696c733a20446563696d616c73206e6f74203c3d20313800000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260129082015271213934b233b29d10273ab636103a37b5b2b760711b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526022908201527f526f6c65733a206163636f756e7420697320746865207a65726f206164647265604082015261737360f01b606082015260800190565b60208082526017908201527f4272696467653a20416c726561647920636c61696d6564000000000000000000604082015260600190565b6020808252601b908201527f4272696467653a206e6f74207772617070656443757272656e63790000000000604082015260600190565b60208082526018908201527f4272696467653a20416c72656164792061636365707465640000000000000000604082015260600190565b602080825260169082015275084e4d2c8ceca74409cead8d84084d8dec6d690c2e6d60531b604082015260600190565b6020808252601c908201527f4272696467653a20416c6c6f77546f6b656e7320697320656d70747900000000604082015260600190565b60208082526018908201527f4272696467653a204e6f742045524337373720746f6b656e0000000000000000604082015260600190565b602080825260169082015275109c9a5919d94e88151e081b9bdd0818dc9bdcdcd95960521b604082015260600190565b602080825260149082015273084e4d2c8ceca7440cccaca40e8dede40d0d2ced60631b604082015260600190565b60208082526022908201527f4f776e61626c653a206e6577206f776e6572206973207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601690820152754272696467653a20416c72656164792065786973747360501b604082015260600190565b60208082526017908201527f4272696467653a20626967676572207468616e20313025000000000000000000604082015260600190565b6020808252601f908201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604082015260600190565b60208082526021908201527f4272696467653a2057726f6e67207472616e73616374696f6e446174614861736040820152600d60fb1b606082015260800190565b600083825260406020830152611eae604083018461344a565b60405181810167ffffffffffffffff8111828210171561417157fe5b604052919050565b60005b8381101561419457818101518382015260200161417c565b8381111561172b5750506000910152565b6001600160a01b03811681146117ba57600080fd5b80151581146117ba57600080fdfea2646970667358221220e143d2279b60c05f738592181a70ec82915a0a581781d565db6d7865329e772a64736f6c63430007060033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":200},"remappings":[]},"optimization_runs":200,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/partial_match/1/0x9F29F9BDA2052884D39F0f032b68aAa14FC363d8/","decoded_constructor_args":null,"compiler_version":"0.7.6+commit.7338295f","is_verified_via_verifier_alliance":false,"verified_at":"2024-05-11T10:02:23.281850Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x608060405234801561001057600080fd5b506141fe806100206000396000f3fe6080604052600436106103025760003560e01c806382dc1ec411610190578063b86f60d2116100dc578063e6ede14d11610095578063eb16136f1161006f578063eb16136f146108a5578063f2fde38b146108c5578063f74032f0146108e5578063fa0caa16146109055761034c565b8063e6ede14d1461085b578063e6fc77441461087b578063ea217091146108905761034c565b8063b86f60d2146107b1578063c4d66de8146107c6578063ca07140c146107e6578063cc3c0f0614610806578063d12e825d14610826578063da6770371461083b5761034c565b8063adc5fb6411610149578063b0e1268e11610123578063b0e1268e14610754578063b50277bb14610769578063b760faf914610789578063b79472621461079c5761034c565b8063adc5fb64146106f4578063ae06c1b714610714578063afad80ac146107345761034c565b806382dc1ec4146106605780638456cb59146106805780638da5cb5b146106955780638f32d59b146106aa578063916dc59d146106bf578063a53d6e6e146106df5761034c565b806346fbf68e1161024f5780636a86319111610208578063715018a6116101e2578063715018a6146105f65780637813bea21461060b5780637ecebe001461062b5780638129fc1c1461064b5761034c565b80636a863191146105ac5780636b0509b1146105cc5780636ef8d66d146105e15761034c565b806346fbf68e146105005780634beea5061461052057806354fd4d501461054057806359a8a867146105625780635c975abb146105775780635d4471291461058c5761034c565b80632fb3b361116102bc57806337e761091161029657806337e76109146104715780633cf3058b1461049e5780633f4ba83a146104cb57806342cdb2c6146104e05761034c565b80632fb3b3611461041c5780633500c1dc1461043c5780633644e5151461045c5761034c565b806223de2914610351578063026976191461037157806307c8f7b0146103a757806311efbf61146103c757806320e3bb00146103dc5780632f3cca4e146103fc5761034c565b3661034c576041546001600160a01b031661031b610925565b6001600160a01b03161461034a5760405162461bcd60e51b815260040161034190613e67565b60405180910390fd5b005b600080fd5b34801561035d57600080fd5b5061034a61036c3660046130ee565b610929565b34801561037d57600080fd5b5061039161038c366004613265565b610b20565b60405161039e91906136c1565b60405180910390f35b3480156103b357600080fd5b5061034a6103c236600461322d565b610b32565b3480156103d357600080fd5b50610391610bb0565b3480156103e857600080fd5b5061034a6103f7366004613396565b610bb6565b34801561040857600080fd5b5061034a610417366004612f6c565b610df1565b34801561042857600080fd5b5061034a61043736600461301a565b610e7a565b34801561044857600080fd5b5061034a610457366004612f6c565b610fea565b34801561046857600080fd5b5061039161107f565b34801561047d57600080fd5b5061049161048c366004613265565b611085565b60405161039e91906136b6565b3480156104aa57600080fd5b506104be6104b9366004613265565b6110aa565b60405161039e919061354d565b3480156104d757600080fd5b5061034a6110c5565b3480156104ec57600080fd5b5061034a6104fb366004612f6c565b611158565b34801561050c57600080fd5b5061049161051b366004612f6c565b6111eb565b34801561052c57600080fd5b5061039161053b366004613298565b6111fe565b34801561054c57600080fd5b50610555611318565b60405161039e919061377d565b34801561056e57600080fd5b50610555611334565b34801561058357600080fd5b506104916113c2565b34801561059857600080fd5b506104916105a7366004612f6c565b6113cb565b3480156105b857600080fd5b5061034a6105c7366004612fa4565b6113e0565b3480156105d857600080fd5b50610391611644565b3480156105ed57600080fd5b5061034a611668565b34801561060257600080fd5b5061034a61167a565b34801561061757600080fd5b5061034a61062636600461319c565b6116ee565b34801561063757600080fd5b50610391610646366004612f6c565b611731565b34801561065757600080fd5b5061034a611743565b34801561066c57600080fd5b5061034a61067b366004612f6c565b6117bd565b34801561068c57600080fd5b5061034a6117ed565b3480156106a157600080fd5b506104be61186d565b3480156106b657600080fd5b50610491611881565b3480156106cb57600080fd5b5061034a6106da366004612f6c565b6118ac565b3480156106eb57600080fd5b506104be611941565b34801561070057600080fd5b5061039161070f36600461327d565b611950565b34801561072057600080fd5b5061034a61072f366004613265565b6119af565b34801561074057600080fd5b5061039161074f3660046131dc565b611a29565b34801561076057600080fd5b506104be611a65565b34801561077557600080fd5b5061039161078436600461327d565b611a74565b61034a610797366004612f6c565b611a87565b3480156107a857600080fd5b50610491611b56565b3480156107bd57600080fd5b506104be611b66565b3480156107d257600080fd5b5061034a6107e1366004612f6c565b611b75565b3480156107f257600080fd5b506104be610801366004613265565b611c40565b34801561081257600080fd5b50610491610821366004613265565b611c5b565b34801561083257600080fd5b5061034a611c70565b34801561084757600080fd5b50610491610856366004613265565b611cc8565b34801561086757600080fd5b506104be610876366004612f6c565b611cdc565b34801561088757600080fd5b50610391611cf7565b34801561089c57600080fd5b506104be611cfd565b3480156108b157600080fd5b5061034a6108c0366004612f6c565b611d0c565b3480156108d157600080fd5b5061034a6108e0366004612f6c565b611d97565b3480156108f157600080fd5b506104be610900366004612f6c565b611dc4565b34801561091157600080fd5b5061034a610920366004612f6c565b611ddf565b3390565b6001600160a01b03881630141561093f57610b16565b6001600160a01b03861630146109675760405162461bcd60e51b815260040161034190613b3b565b6000610971610925565b60405163555ddc6560e11b8152909150600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca906109d09085907fac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce217705490600401613655565b60206040518083038186803b1580156109e857600080fd5b505afa1580156109fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a209190612f88565b6001600160a01b03161415610a475760405162461bcd60e51b815260040161034190613f3c565b83151580610a645750610a62886001600160a01b0316611e7a565b155b610a805760405162461bcd60e51b815260040161034190613ba2565b60008415610acc57610ac786868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611eb692505050565b610ace565b885b9050610b13828a838a8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ebd92505050565b50505b5050505050505050565b60426020526000908152604090205481565b610b3a611881565b610b565760405162461bcd60e51b815260040161034190613db9565b6040805460ff60a01b1916600160a01b83151581029190911780835591517f983e436223c000a441c2443b394ca5fb4669a513fe86dc1dd44494047b514ad992610ba59260ff910416906136b6565b60405180910390a150565b60375490565b610bbe611881565b610bda5760405162461bcd60e51b815260040161034190613db9565b6001600160a01b038616610c005760405162461bcd60e51b815260040161034190613d8d565b6001600160a01b038087166000908152603b6020526040902054168015610c395760405162461bcd60e51b81526004016103419061405d565b6000610c4487612170565b9050600060388787604051602001610c5e939291906134d4565b60408051601f1981840301815282825290546326d9e96360e01b83529092506001600160a01b0316906326d9e96390610ca190889088908690889060040161372e565b602060405180830381600087803b158015610cbb57600080fd5b505af1158015610ccf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf39190612f88565b6001600160a01b03808b166000818152603b6020908152604080832080548688166001600160a01b03199182168117909255908452603c909252918290208054909116909217909155603f5490516378bf2b5360e01b815292955016906378bf2b5390610d669086908e90600401613655565b600060405180830381600087803b158015610d8057600080fd5b505af1158015610d94573d6000803e3d6000fd5b50505050886001600160a01b0316836001600160a01b03167f2ef93c4e96a4ef0b19497ff60c9e7360a8734f3d2cd27ae5318e43851734d17f8385604051610ddd929190613790565b60405180910390a350505050505050505050565b600054610100900460ff1680610e0a575060005460ff16155b610e265760405162461bcd60e51b8152600401610341906139eb565b600054610100900460ff16158015610e51576000805460ff1961ff0019909116610100171660011790555b610e5a82611d0c565b6034805460ff191690558015610e76576000805461ff00191690555b5050565b600054610100900460ff1680610e93575060005460ff16155b610eaf5760405162461bcd60e51b8152600401610341906139eb565b600054610100900460ff16158015610eda576000805460ff1961ff0019909116610100171660011790555b610ee386611b75565b610eec86610df1565b8151610eff906038906020850190612e48565b50603f80546001600160a01b038087166001600160a01b031992831617909255604080548684169083161781556036805493891693909216929092179055516329965a1d60e01b8152731820a4b7618bde71dce8cdc73aab6c95905fad24906329965a1d90610f969030907fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b908290600401613561565b600060405180830381600087803b158015610fb057600080fd5b505af1158015610fc4573d6000803e3d6000fd5b50505050610fd0611c70565b8015610fe2576000805461ff00191690555b505050505050565b610ff2611881565b61100e5760405162461bcd60e51b815260040161034190613db9565b6001600160a01b0381166110345760405162461bcd60e51b815260040161034190613adc565b604180546001600160a01b0319166001600160a01b0383161790556040517f0966c958966f6fac9ff807af074f8117eb2e9ce2b76390db7a158e9bdeb2485c90610ba590839061354d565b60395481565b6000818152604260209081526040808320548352603e90915290205460ff165b919050565b6044602052600090815260409020546001600160a01b031681565b6110d061051b610925565b6110ec5760405162461bcd60e51b815260040161034190613a33565b60345460ff1661110e5760405162461bcd60e51b8152600401610341906137f7565b6034805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611141610925565b60405161114e919061354d565b60405180910390a1565b611160611881565b61117c5760405162461bcd60e51b815260040161034190613db9565b6001600160a01b0381166111a25760405162461bcd60e51b815260040161034190613cd4565b604080546001600160a01b0319166001600160a01b038316178155517f619936bc6e3618d0b8dc69bcc70134fe9d88f9967f3a8b8304e318369252162590610ba590839061354d565b60006111f86033836121a3565b92915050565b6000428510156112205760405162461bcd60e51b815260040161034190613cab565b600061123c611234368b90038b018b613308565b8989896121eb565b90506000600182878787604051600081526020016040526040516112639493929190613710565b6020604051602081039080840390855afa158015611285573d6000803e3d6000fd5b5050604051601f1901519150600090506112a260208c018c612f6c565b6001600160a01b0316141580156112d657506112c160208b018b612f6c565b6001600160a01b0316816001600160a01b0316145b6112f25760405162461bcd60e51b815260040161034190613a7b565b61130a8a6113036020820182612f6c565b8b8b612280565b9a9950505050505050505050565b604080518082019091526002815261763360f01b602082015290565b6038805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156113ba5780601f1061138f576101008083540402835291602001916113ba565b820191906000526020600020905b81548152906001019060200180831161139d57829003601f168201915b505050505081565b60345460ff1690565b603d6020526000908152604090205460ff1681565b60345460ff16156114035760405162461bcd60e51b815260040161034190613c4a565b60358054600101908190556036546001600160a01b0316611422610925565b6001600160a01b0316146114485760405162461bcd60e51b815260040161034190613b72565b6001600160a01b0388166000908152603d602052604090205460ff168061148857506001600160a01b038881166000908152603b60205260409020541615155b6114a45760405162461bcd60e51b815260040161034190613b0c565b6001600160a01b0386166114ca5760405162461bcd60e51b815260040161034190613c21565b600085116114ea5760405162461bcd60e51b815260040161034190613ab2565b836115075760405162461bcd60e51b815260040161034190613ed5565b826115245760405162461bcd60e51b815260040161034190613954565b600083815260426020526040902054156115505760405162461bcd60e51b815260040161034190613e9e565b600061155f8787878787611a29565b6000818152603e602052604090205490915060ff16156115915760405162461bcd60e51b815260040161034190613e30565b60008481526042602090815260408083208490556043825280832080546001600160a01b03199081166001600160a01b038f811691821790935560449094529382902080549094168c821617909355519189169186907f2858b8803acb87882fd2de49ce7572ae3e741fb8073cbe772fa50ce00bdfba229061161a908d908c908c908b90613584565b60405180910390a4506035548114610b165760405162461bcd60e51b8152600401610341906137b2565b7ff18ceda3f6355f78c234feba066041a50f6557bfb600201e2a71a89e2dd8043381565b611678611673610925565b612499565b565b611682611881565b61169e5760405162461bcd60e51b815260040161034190613db9565b60345460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a360348054610100600160a81b0319169055565b60006116f8610925565b905061170f6001600160a01b0385168230856124db565b61172b8482858560405180602001604052806000815250611ebd565b50505050565b60456020526000908152604090205481565b600054610100900460ff168061175c575060005460ff16155b6117785760405162461bcd60e51b8152600401610341906139eb565b600054610100900460ff161580156117a3576000805460ff1961ff0019909116610100171660011790555b600160355580156117ba576000805461ff00191690555b50565b6117c861051b610925565b6117e45760405162461bcd60e51b815260040161034190613a33565b6117ba81612533565b6117f861051b610925565b6118145760405162461bcd60e51b815260040161034190613a33565b60345460ff16156118375760405162461bcd60e51b815260040161034190613c4a565b6034805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611141610925565b60345461010090046001600160a01b031690565b60345460009061010090046001600160a01b031661189d610925565b6001600160a01b031614905090565b6118b4611881565b6118d05760405162461bcd60e51b815260040161034190613db9565b6001600160a01b0381166118f65760405162461bcd60e51b815260040161034190613f05565b603f80546001600160a01b0319166001600160a01b0383161790556040517f5f2c1fe803fd576d8af05ea156011cc9cc8c025bda24c1e85772fc05a0b3f1e390610ba590839061354d565b603f546001600160a01b031681565b60608101356000908152604460205260408120546001600160a01b0316611975610925565b6001600160a01b03161461199b5760405162461bcd60e51b815260040161034190613924565b6111f8826119a7610925565b600080612280565b6119b7611881565b6119d35760405162461bcd60e51b815260040161034190613db9565b6103e881106119f45760405162461bcd60e51b81526004016103419061408d565b60378190556040517f97e97c577f03bda90e2c9739011ec065ed5fbfb36ae217d20bb0d9be95e160cd90610ba59083906136c1565b60008383878785604051602001611a44959493929190613476565b60405160208183030381529060405280519060200120905095945050505050565b6041546001600160a01b031681565b60006111f8826119a76020820182612f6c565b6000611a91610925565b6041549091506001600160a01b0316611abc5760405162461bcd60e51b815260040161034190613c74565b604160009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015611b0c57600080fd5b505af1158015611b20573d6000803e3d6000fd5b5050505050610e76604160009054906101000a90046001600160a01b031682843460405180602001604052806000815250611ebd565b604054600160a01b900460ff1681565b6040546001600160a01b031681565b600054610100900460ff1680611b8e575060005460ff16155b611baa5760405162461bcd60e51b8152600401610341906139eb565b600054610100900460ff16158015611bd5576000805460ff1961ff0019909116610100171660011790555b60348054610100600160a81b0319166101006001600160a01b0385811682029290921792839055604051920416906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015610e76576000805461ff00191690555050565b6043602052600090815260409020546001600160a01b031681565b603e6020526000908152604090205460ff1681565b6000469050611cc26040518060400160405280601081526020016f52534b20546f6b656e2042726964676560801b815250604051806040016040528060018152602001603160f81b8152508330612575565b60395550565b600090815260426020526040902054151590565b603b602052600090815260409020546001600160a01b031681565b61271081565b6036546001600160a01b031690565b600054610100900460ff1680611d25575060005460ff16155b611d415760405162461bcd60e51b8152600401610341906139eb565b600054610100900460ff16158015611d6c576000805460ff1961ff0019909116610100171660011790555b611d75826111eb565b611d8257611d8282612533565b8015610e76576000805461ff00191690555050565b611d9f611881565b611dbb5760405162461bcd60e51b815260040161034190613db9565b6117ba816125cc565b603c602052600090815260409020546001600160a01b031681565b611de7611881565b611e035760405162461bcd60e51b815260040161034190613db9565b6001600160a01b038116611e295760405162461bcd60e51b81526004016103419061388b565b603680546001600160a01b0319166001600160a01b0383811691909117918290556040517f4a41a4d11aaf0c0c9e4311ac1d68b2b0134556da594779a2a35b0ddf7cd1eafb92610ba592169061354d565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611eae57508115155b949350505050565b6014015190565b604054600160a01b900460ff1615611ee75760405162461bcd60e51b8152600401610341906138f9565b60345460ff1615611f0a5760405162461bcd60e51b815260040161034190613c4a565b603580546001908101918290556001600160a01b0387166000908152603d60205260408120805460ff1916909217909155603754611f579061271090611f51908790612659565b9061269a565b90506000611f6585836126dc565b90506000611f728961271e565b905085601260ff831614611f9757611f948760ff601285900316600a0a612659565b90505b603f54604051638c34bc5560e01b81526001600160a01b0390911690638c34bc5590611fc9908d908590600401613655565b600060405180830381600087803b158015611fe357600080fd5b505af1158015611ff7573d6000803e3d6000fd5b5050506001600160a01b03808c166000908152603c60205260409020548c925016156120d157506001600160a01b03808b166000908152603c6020526040812054909116906120458c6127da565b905060006120538683612882565b905061205f87826128c4565b965061206b86826126dc565b60405163fe9d930360e01b81529096506001600160a01b038e169063fe9d93039061209c9089908d9060040161413c565b600060405180830381600087803b1580156120b657600080fd5b505af11580156120ca573d6000803e3d6000fd5b5050505050505b886001600160a01b03168a6001600160a01b0316826001600160a01b03167f1e90de9ae4d02420648a650f45f089a1be18fbca324092544ea626f9833212b0878b60405161212092919061413c565b60405180910390a4841561214a5761214a61213961186d565b6001600160a01b038d1690876128e9565b50505050506035548114610fe25760405162461bcd60e51b8152600401610341906137b2565b600060128260ff1611156121965760405162461bcd60e51b815260040161034190613d15565b5060120360ff16600a0a90565b60006001600160a01b0382166121cb5760405162461bcd60e51b815260040161034190613dee565b506001600160a01b03166000908152602091909152604090205460ff1690565b603954845160208087015160608801516001600160a01b03841660009081526045845260408082208054600181019091559051919661227796909561225c957ff18ceda3f6355f78c234feba066041a50f6557bfb600201e2a71a89e2dd8043395929490938d928d928d91016136ca565b6040516020818303038152906040528051906020012061290d565b95945050505050565b603580546001019081905560608501356000908152604360205260408120549091906001600160a01b0316806122c85760405162461bcd60e51b815260040161034190613f73565b60006122f96122da60208a018a612f6c565b60208a013560408b013560608c013561074f60a08e0160808f01613430565b6060890135600090815260426020526040902054909150811461232e5760405162461bcd60e51b8152600401610341906140fb565b6000818152603e602052604090205460ff161561235d5760405162461bcd60e51b815260040161034190613e30565b6000818152603e60209081526040808320805460ff191660011790556001600160a01b0385168352603d90915290205460ff16156123ad576123a682888a60200135898961292c565b93506123c1565b6123be82888a602001358989612aa2565b93505b6123ce6020890189612f6c565b6001600160a01b0316826001600160a01b031689606001357f42b1cb6263e8da47edf0583516eda1de16f729d26282f5791dc5b7af1010e925604460008d60600135815260200190815260200160002060009054906101000a90046001600160a01b03168c602001358d604001358e608001602081019061244f9190613430565b8e8e8e604051612465979695949392919061366e565b60405180910390a4505060355481146124905760405162461bcd60e51b8152600401610341906137b2565b50949350505050565b6124a4603382612c39565b6040516001600160a01b038216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b61172b846323b872dd60e01b8585856040516024016124fc93929190613631565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612c81565b61253e603382612d65565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b6001600160a01b0381166125f25760405162461bcd60e51b815260040161034190613fd1565b6034546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600082612668575060006111f8565b8282028284828161267557fe5b04146126935760405162461bcd60e51b815260040161034190613d4c565b9392505050565b600061269383836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612db1565b600061269383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612de8565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b1790529051600091829182916001600160a01b0386169161276491906134b8565b600060405180830381855afa9150503d806000811461279f576040519150601f19603f3d011682016040523d82523d6000602084013e6127a4565b606091505b5091509150816127c65760405162461bcd60e51b81526004016103419061385c565b80806020019051810190611eae919061337e565b60408051600481526024810182526020810180516001600160e01b031663556f0dc760e01b1790529051600091829182916001600160a01b0386169161282091906134b8565b600060405180830381855afa9150503d806000811461285b576040519150601f19603f3d011682016040523d82523d6000602084013e612860565b606091505b5091509150816127c65760405162461bcd60e51b815260040161034190613bea565b600061269383836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815250612e14565b6000828201838110156126935760405162461bcd60e51b8152600401610341906138c2565b6129088363a9059cbb60e01b84846040516024016124fc929190613655565b505050565b60405161190160f01b8152600281019290925260228201526042902090565b6000806129388761271e565b60ff1690506000612950866012849003600a0a61269a565b9050808411156129725760405162461bcd60e51b815260040161034190613fa3565b60415484820393506001600160a01b0389811691161415612a6957604154604051632e1a7d4d60e01b81526001600160a01b0390911690632e1a7d4d906129bd9084906004016136c1565b600060405180830381600087803b1580156129d757600080fd5b505af11580156129eb573d6000803e3d6000fd5b50506040516001600160a01b038a16925085156108fc02915085906000818181858888f19350505050158015612a25573d6000803e3d6000fd5b508315612a64576040516001600160a01b0386169085156108fc029086906000818181858888f19350505050158015612a62573d6000803e3d6000fd5b505b612a97565b612a7d6001600160a01b03891688856128e9565b8315612a9757612a976001600160a01b03891686866128e9565b505095945050505050565b6001600160a01b038086166000908152603b6020908152604080832054815163556f0dc760e01b81529151939416928492849263556f0dc79260048083019392829003018186803b158015612af657600080fd5b505afa158015612b0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2e919061337e565b90506000612b3c8783612659565b905080851115612b5e5760405162461bcd60e51b815260040161034190613fa3565b604051630dcdc7dd60e41b815285820394506001600160a01b0384169063dcdc7dd090612b91908b9088906004016135fb565b600060405180830381600087803b158015612bab57600080fd5b505af1158015612bbf573d6000803e3d6000fd5b505050506000851115612c2d57604051630dcdc7dd60e41b81526001600160a01b0384169063dcdc7dd090612bfa90899089906004016135b0565b600060405180830381600087803b158015612c1457600080fd5b505af1158015612c28573d6000803e3d6000fd5b505050505b50505095945050505050565b612c4382826121a3565b612c5f5760405162461bcd60e51b815260040161034190613981565b6001600160a01b0316600090815260209190915260409020805460ff19169055565b612c93826001600160a01b0316611e7a565b612caf5760405162461bcd60e51b8152600401610341906140c4565b600080836001600160a01b031683604051612cca91906134b8565b6000604051808303816000865af19150503d8060008114612d07576040519150601f19603f3d011682016040523d82523d6000602084013e612d0c565b606091505b509150915081612d2e5760405162461bcd60e51b8152600401610341906139b6565b80511561172b5780806020019051810190612d499190613249565b61172b5760405162461bcd60e51b815260040161034190614013565b612d6f82826121a3565b15612d8c5760405162461bcd60e51b815260040161034190613825565b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b60008183612dd25760405162461bcd60e51b8152600401610341919061377d565b506000838581612dde57fe5b0495945050505050565b60008184841115612e0c5760405162461bcd60e51b8152600401610341919061377d565b505050900390565b60008183612e355760405162461bcd60e51b8152600401610341919061377d565b50828481612e3f57fe5b06949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282612e7e5760008555612ec4565b82601f10612e9757805160ff1916838001178555612ec4565b82800160010185558215612ec4579182015b82811115612ec4578251825591602001919060010190612ea9565b50612ed0929150612ed4565b5090565b5b80821115612ed05760008155600101612ed5565b60008083601f840112612efa578182fd5b50813567ffffffffffffffff811115612f11578182fd5b602083019150836020828501011115612f2957600080fd5b9250929050565b600060a08284031215612f41578081fd5b50919050565b803563ffffffff811681146110a557600080fd5b803560ff811681146110a557600080fd5b600060208284031215612f7d578081fd5b8135612693816141a5565b600060208284031215612f99578081fd5b8151612693816141a5565b600080600080600080600060e0888a031215612fbe578283fd5b8735612fc9816141a5565b96506020880135612fd9816141a5565b95506040880135612fe9816141a5565b9450606088013593506080880135925060a0880135915061300c60c08901612f47565b905092959891949750929550565b600080600080600060a08688031215613031578081fd5b853561303c816141a5565b945060208681013561304d816141a5565b9450604087013561305d816141a5565b9350606087013561306d816141a5565b9250608087013567ffffffffffffffff80821115613089578384fd5b818901915089601f83011261309c578384fd5b8135818111156130a857fe5b6130ba601f8201601f19168501614155565b91508082528a848285010111156130cf578485fd5b8084840185840137810190920192909252949793965091945092919050565b60008060008060008060008060c0898b031215613109578081fd5b8835613114816141a5565b97506020890135613124816141a5565b96506040890135613134816141a5565b955060608901359450608089013567ffffffffffffffff80821115613157578283fd5b6131638c838d01612ee9565b909650945060a08b013591508082111561317b578283fd5b506131888b828c01612ee9565b999c989b5096995094979396929594505050565b6000806000606084860312156131b0578081fd5b83356131bb816141a5565b925060208401356131cb816141a5565b929592945050506040919091013590565b600080600080600060a086880312156131f3578283fd5b85356131fe816141a5565b945060208601359350604086013592506060860135915061322160808701612f47565b90509295509295909350565b60006020828403121561323e578081fd5b8135612693816141ba565b60006020828403121561325a578081fd5b8151612693816141ba565b600060208284031215613276578081fd5b5035919050565b600060a0828403121561328e578081fd5b6126938383612f30565b6000806000806000806000610160888a0312156132b3578081fd5b6132bd8989612f30565b965060a08801356132cd816141a5565b955060c0880135945060e088013593506132ea6101008901612f5b565b92506101208801359150610140880135905092959891949750929550565b600060a08284031215613319578081fd5b60405160a0810181811067ffffffffffffffff8211171561333657fe5b6040528235613344816141a5565b8082525060208301356020820152604083013560408201526060830135606082015261337260808401612f47565b60808201529392505050565b60006020828403121561338f578081fd5b5051919050565b600080600080600080600060a0888a0312156133b0578081fd5b8735965060208801356133c2816141a5565b95506133d060408901612f5b565b9450606088013567ffffffffffffffff808211156133ec578283fd5b6133f88b838c01612ee9565b909650945060808a0135915080821115613410578283fd5b5061341d8a828b01612ee9565b989b979a50959850939692959293505050565b600060208284031215613441578081fd5b61269382612f47565b60008151808452613462816020860160208601614179565b601f01601f19169290920160200192915050565b948552602085019390935260609190911b6bffffffffffffffffffffffff19166040840152605483015260e01b6001600160e01b031916607482015260780190565b600082516134ca818460208701614179565b9190910192915050565b60008085546001808216600081146134f3576001811461350a57613539565b60ff198316865260028304607f1686019350613539565b600283048986526020808720875b838110156135315781548a820152908501908201613518565b505050860193505b505050838582379092019182525092915050565b6001600160a01b0391909116815260200190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b039490941684526020840192909252604083015263ffffffff16606082015260800190565b6001600160a01b03929092168252602082015260806040820181905260009082015260a060608201819052600b908201526a72656c617965722066656560a81b60c082015260e00190565b6001600160a01b039290921682526020820152608060408201819052600090820181905260a06060830181905282015260c00190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0397881681526020810196909652604086019490945263ffffffff9290921660608501528416608084015290921660a082015260c081019190915260e00190565b901515815260200190565b90815260200190565b9788526001600160a01b039687166020890152604088019590955260608701939093529316608085015260a084019290925260c083019190915260e08201526101000190565b93845260ff9290921660208401526040830152606082015260800190565b600060608252846060830152848660808401378060808684010152601f19601f8601168201608083820301602084015261376b608082018661344a565b91505082604083015295945050505050565b600060208252612693602083018461344a565b6000604082526137a3604083018561344a565b90508260208301529392505050565b60208082526025908201527f5265656e7472616e637947756172643a206e6f207265656e7472616e7420616c6040820152641b1bddd95960da1b606082015260800190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b6020808252601f908201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604082015260600190565b6020808252601590820152744c69625574696c733a204e6f20646563696d616c7360581b604082015260600190565b6020808252601b908201527f4272696467653a2046656465726174696f6e20697320656d7074790000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601190820152704272696467653a20557067726164696e6760781b604082015260600190565b602080825260169082015275213934b233b29d1034b73b30b634b21039b2b73232b960511b604082015260600190565b602080825260139082015272084e4d2c8ceca74409cead8d840a8f090c2e6d606b1b604082015260600190565b6020808252818101527f526f6c65733a206163636f756e7420646f65736e2774206861766520726f6c65604082015260600190565b6020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b60208082526028908201527f436f6e747261637420696e7374616e636520697320616c726561647920696e696040820152671d1a585b1a5e995960c21b606082015260800190565b60208082526028908201527f506175736572526f6c653a2063616c6c657220646f65736e277420686176652060408201526774686520726f6c6560c01b606082015260800190565b60208082526019908201527f4272696467653a20494e56414c49445f5349474e415455524500000000000000604082015260600190565b60208082526010908201526f04272696467653a20416d6f756e7420360841b604082015260600190565b6020808252601690820152754272696467653a20777261707020697320656d70747960501b604082015260600190565b602080825260159082015274213934b233b29d102ab735b737bbb7103a37b5b2b760591b604082015260600190565b6020808252601b908201527f4272696467653a204e6f7420746f207468697320616464726573730000000000604082015260600190565b602080825260169082015275213934b233b29d102737ba102332b232b930ba34b7b760511b604082015260600190565b60208082526028908201527f4272696467653a2053706563696679207265636569766572206164647265737360408201526720696e206461746160c01b606082015260800190565b60208082526018908201527f4c69625574696c733a204e6f206772616e756c61726974790000000000000000604082015260600190565b6020808252600f908201526e4272696467653a204e756c6c20546f60881b604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601d908201527f4272696467653a207772617070656443757272656e637920656d707479000000604082015260600190565b6020808252600f908201526e109c9a5919d94e8811561412549151608a1b604082015260600190565b60208082526021908201527f4272696467653a2053696465546f6b656e466163746f727920697320656d70746040820152607960f81b606082015260800190565b6020808252601c908201527f4c69625574696c733a20446563696d616c73206e6f74203c3d20313800000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260129082015271213934b233b29d10273ab636103a37b5b2b760711b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526022908201527f526f6c65733a206163636f756e7420697320746865207a65726f206164647265604082015261737360f01b606082015260800190565b60208082526017908201527f4272696467653a20416c726561647920636c61696d6564000000000000000000604082015260600190565b6020808252601b908201527f4272696467653a206e6f74207772617070656443757272656e63790000000000604082015260600190565b60208082526018908201527f4272696467653a20416c72656164792061636365707465640000000000000000604082015260600190565b602080825260169082015275084e4d2c8ceca74409cead8d84084d8dec6d690c2e6d60531b604082015260600190565b6020808252601c908201527f4272696467653a20416c6c6f77546f6b656e7320697320656d70747900000000604082015260600190565b60208082526018908201527f4272696467653a204e6f742045524337373720746f6b656e0000000000000000604082015260600190565b602080825260169082015275109c9a5919d94e88151e081b9bdd0818dc9bdcdcd95960521b604082015260600190565b602080825260149082015273084e4d2c8ceca7440cccaca40e8dede40d0d2ced60631b604082015260600190565b60208082526022908201527f4f776e61626c653a206e6577206f776e6572206973207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601690820152754272696467653a20416c72656164792065786973747360501b604082015260600190565b60208082526017908201527f4272696467653a20626967676572207468616e20313025000000000000000000604082015260600190565b6020808252601f908201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604082015260600190565b60208082526021908201527f4272696467653a2057726f6e67207472616e73616374696f6e446174614861736040820152600d60fb1b606082015260800190565b600083825260406020830152611eae604083018461344a565b60405181810167ffffffffffffffff8111828210171561417157fe5b604052919050565b60005b8381101561419457818101518382015260200161417c565b8381111561172b5750506000910152565b6001600160a01b03811681146117ba57600080fd5b80151581146117ba57600080fdfea2646970667358221220e143d2279b60c05f738592181a70ec82915a0a581781d565db6d7865329e772a64736f6c63430007060033","name":"Bridge","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"istanbul","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[],"certified":false,"conflicting_implementations":null,"abi":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_transactionHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"_originalTokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_blockHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_logIndex","type":"uint256"}],"name":"AcceptedCrossTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newAllowTokens","type":"address"}],"name":"AllowTokensChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_transactionHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"_originalTokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"address","name":"_sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_blockHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_logIndex","type":"uint256"},{"indexed":false,"internalType":"address","name":"_reciever","type":"address"},{"indexed":false,"internalType":"address","name":"_relayer","type":"address"},{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_userData","type":"bytes"}],"name":"Cross","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newFederation","type":"address"}],"name":"FederationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"FeePercentageChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_newSideTokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"_originalTokenAddress","type":"address"},{"indexed":false,"internalType":"string","name":"_newSymbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"_granularity","type":"uint256"}],"name":"NewSideToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"PauserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"PauserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newSideTokenFactory","type":"address"}],"name":"SideTokenFactoryChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_isUpgrading","type":"bool"}],"name":"Upgrading","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_wrappedCurrency","type":"address"}],"name":"WrappedCurrencyChanged","type":"event"},{"inputs":[],"name":"CLAIM_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"__Pausable_init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"__PauserRol_init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_originalTokenAddress","type":"address"},{"internalType":"address payable","name":"_from","type":"address"},{"internalType":"address payable","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes32","name":"_blockHash","type":"bytes32"},{"internalType":"bytes32","name":"_transactionHash","type":"bytes32"},{"internalType":"uint32","name":"_logIndex","type":"uint32"}],"name":"acceptTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addPauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allowTokens","outputs":[{"internalType":"contract IAllowTokens","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAllowTokens","type":"address"}],"name":"changeAllowTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFederation","type":"address"}],"name":"changeFederation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSideTokenFactory","type":"address"}],"name":"changeSideTokenFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionHash","type":"bytes32"},{"internalType":"uint32","name":"logIndex","type":"uint32"}],"internalType":"struct IBridge.ClaimData","name":"_claimData","type":"tuple"}],"name":"claim","outputs":[{"internalType":"uint256","name":"receivedAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionHash","type":"bytes32"},{"internalType":"uint32","name":"logIndex","type":"uint32"}],"internalType":"struct IBridge.ClaimData","name":"_claimData","type":"tuple"}],"name":"claimFallback","outputs":[{"internalType":"uint256","name":"receivedAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionHash","type":"bytes32"},{"internalType":"uint32","name":"logIndex","type":"uint32"}],"internalType":"struct IBridge.ClaimData","name":"_claimData","type":"tuple"},{"internalType":"address payable","name":"_relayer","type":"address"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"claimGasless","outputs":[{"internalType":"uint256","name":"receivedAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"claimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_typeId","type":"uint256"},{"internalType":"address","name":"_originalTokenAddress","type":"address"},{"internalType":"uint8","name":"_originalTokenDecimals","type":"uint8"},{"internalType":"string","name":"_originalTokenSymbol","type":"string"},{"internalType":"string","name":"_originalTokenName","type":"string"}],"name":"createSideToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"depositTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"feePercentageDivider","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFederation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes32","name":"_blockHash","type":"bytes32"},{"internalType":"bytes32","name":"_transactionHash","type":"bytes32"},{"internalType":"uint32","name":"_logIndex","type":"uint32"}],"name":"getTransactionDataHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"hasBeenClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"hasCrossed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initDomainSeparator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"},{"internalType":"address","name":"_federation","type":"address"},{"internalType":"address","name":"_allowTokens","type":"address"},{"internalType":"address","name":"_sideTokenFactory","type":"address"},{"internalType":"string","name":"_symbolPrefix","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isPauser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isUpgrading","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"knownTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mappedTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"originalTokenAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"originalTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenToUse","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"receiveTokensTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renouncePauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"senderAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setFeePercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isUpgrading","type":"bool"}],"name":"setUpgrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wrappedCurrency","type":"address"}],"name":"setWrappedCurrency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sideTokenFactory","outputs":[{"internalType":"contract ISideTokenFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbolPrefix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"tokensReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"transactionsDataHashes","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"wrappedCurrency","outputs":[{"internalType":"contract IWrapped","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":null}