@keep-network/tbtc-v2 1.6.0-dev.0 → 1.6.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/artifacts/BLS.json +1 -1
  2. package/artifacts/Bank.json +3 -3
  3. package/artifacts/BeaconAuthorization.json +1 -1
  4. package/artifacts/BeaconDkg.json +1 -1
  5. package/artifacts/BeaconDkgValidator.json +1 -1
  6. package/artifacts/BeaconInactivity.json +1 -1
  7. package/artifacts/BeaconSortitionPool.json +3 -3
  8. package/artifacts/Bridge.json +5 -5
  9. package/artifacts/BridgeGovernance.json +2 -2
  10. package/artifacts/BridgeGovernanceParameters.json +2 -2
  11. package/artifacts/Deposit.json +2 -2
  12. package/artifacts/DepositSweep.json +2 -2
  13. package/artifacts/DonationVault.json +3 -3
  14. package/artifacts/EcdsaDkgValidator.json +1 -1
  15. package/artifacts/EcdsaInactivity.json +1 -1
  16. package/artifacts/EcdsaSortitionPool.json +3 -3
  17. package/artifacts/Fraud.json +2 -2
  18. package/artifacts/KeepRegistry.json +1 -1
  19. package/artifacts/KeepStake.json +2 -2
  20. package/artifacts/KeepToken.json +2 -2
  21. package/artifacts/KeepTokenStaking.json +1 -1
  22. package/artifacts/LightRelay.json +18 -18
  23. package/artifacts/LightRelayMaintainerProxy.json +8 -8
  24. package/artifacts/MaintainerProxy.json +19 -19
  25. package/artifacts/MovingFunds.json +2 -2
  26. package/artifacts/NuCypherStakingEscrow.json +1 -1
  27. package/artifacts/NuCypherToken.json +2 -2
  28. package/artifacts/RandomBeacon.json +2 -2
  29. package/artifacts/RandomBeaconChaosnet.json +2 -2
  30. package/artifacts/RandomBeaconGovernance.json +2 -2
  31. package/artifacts/Redemption.json +2 -2
  32. package/artifacts/ReimbursementPool.json +2 -2
  33. package/artifacts/T.json +2 -2
  34. package/artifacts/TBTC.json +3 -3
  35. package/artifacts/TBTCToken.json +3 -3
  36. package/artifacts/TBTCVault.json +23 -23
  37. package/artifacts/TokenStaking.json +1 -1
  38. package/artifacts/TokenholderGovernor.json +9 -9
  39. package/artifacts/TokenholderTimelock.json +8 -8
  40. package/artifacts/VendingMachine.json +3 -3
  41. package/artifacts/VendingMachineKeep.json +1 -1
  42. package/artifacts/VendingMachineNuCypher.json +1 -1
  43. package/artifacts/VendingMachineV2.json +3 -3
  44. package/artifacts/VendingMachineV3.json +3 -3
  45. package/artifacts/WalletCoordinator.json +5 -5
  46. package/artifacts/WalletRegistry.json +5 -5
  47. package/artifacts/WalletRegistryGovernance.json +2 -2
  48. package/artifacts/Wallets.json +2 -2
  49. package/artifacts/solcInputs/{6cc4a0b423ac26dbfcae644b54bee6ae.json → d2d7e276da75d7184610fe11a4a103b7.json} +4 -1
  50. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  51. package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
  52. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.dbg.json +1 -1
  53. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
  54. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
  55. package/build/contracts/bridge/BridgeGovernanceParameters.sol/BridgeGovernanceParameters.dbg.json +1 -1
  56. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
  57. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +1 -1
  58. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +1 -1
  59. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +1 -1
  60. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +1 -1
  61. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.dbg.json +1 -1
  62. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +1 -1
  63. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +1 -1
  64. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +1 -1
  65. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +1 -1
  66. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  67. package/build/contracts/bridge/VendingMachineV2.sol/VendingMachineV2.dbg.json +1 -1
  68. package/build/contracts/bridge/VendingMachineV3.sol/VendingMachineV3.dbg.json +1 -1
  69. package/build/contracts/bridge/WalletCoordinator.sol/WalletCoordinator.dbg.json +1 -1
  70. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +1 -1
  71. package/build/contracts/l2/L2TBTC.sol/L2TBTC.dbg.json +1 -1
  72. package/build/contracts/l2/L2WormholeGateway.sol/IWormholeTokenBridge.dbg.json +1 -1
  73. package/build/contracts/l2/L2WormholeGateway.sol/L2WormholeGateway.dbg.json +1 -1
  74. package/build/contracts/l2/L2WormholeGateway.sol/L2WormholeGateway.json +2 -15
  75. package/build/contracts/maintainer/MaintainerProxy.sol/MaintainerProxy.dbg.json +1 -1
  76. package/build/contracts/relay/LightRelay.sol/ILightRelay.dbg.json +1 -1
  77. package/build/contracts/relay/LightRelay.sol/LightRelay.dbg.json +1 -1
  78. package/build/contracts/relay/LightRelay.sol/RelayUtils.dbg.json +1 -1
  79. package/build/contracts/relay/LightRelayMaintainerProxy.sol/LightRelayMaintainerProxy.dbg.json +1 -1
  80. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  81. package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +1 -1
  82. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  83. package/build/contracts/vault/TBTCOptimisticMinting.sol/TBTCOptimisticMinting.dbg.json +1 -1
  84. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  85. package/contracts/l2/L2WormholeGateway.sol +7 -27
  86. package/deploy/01_deploy_light_relay.ts +3 -0
  87. package/deploy/09_deploy_bridge_governance.ts +5 -2
  88. package/deploy/19_authorize_spv_maintainer_in_bridge.ts +3 -3
  89. package/deploy/24_transfer_tbtc_ownership.ts +1 -1
  90. package/deploy/28_authorize_bridge_in_reimbursement_pool.ts +1 -1
  91. package/deploy/40_authorize_light_relay_maintainer_proxy_in_reimbursement_pool.ts +1 -1
  92. package/deploy/41_authorize_light_relay_maintainer_proxy_in_light_relay.ts +3 -1
  93. package/export/artifacts/@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol/BTCUtils.json +20 -20
  94. package/export/artifacts/@keep-network/ecdsa/contracts/EcdsaDkgValidator.sol/EcdsaDkgValidator.json +1986 -1986
  95. package/export/artifacts/@keep-network/ecdsa/contracts/libraries/EcdsaDkg.sol/EcdsaDkg.json +20 -20
  96. package/export/artifacts/@keep-network/ecdsa/contracts/libraries/EcdsaInactivity.sol/EcdsaInactivity.json +1836 -1836
  97. package/export/artifacts/@keep-network/random-beacon/contracts/ReimbursementPool.sol/ReimbursementPool.json +545 -545
  98. package/export/artifacts/@keep-network/sortition-pools/contracts/Chaosnet.sol/Chaosnet.json +506 -506
  99. package/export/artifacts/@keep-network/sortition-pools/contracts/Rewards.sol/Rewards.json +23 -23
  100. package/export/artifacts/@keep-network/sortition-pools/contracts/SortitionPool.sol/SortitionPool.json +2456 -2456
  101. package/export/artifacts/@keep-network/sortition-pools/contracts/SortitionTree.sol/SortitionTree.json +465 -465
  102. package/export/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.json +568 -568
  103. package/export/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json +603 -603
  104. package/export/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json +1001 -1001
  105. package/export/artifacts/@openzeppelin/contracts/token/ERC721/ERC721.sol/ERC721.json +1877 -1877
  106. package/export/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.json +654 -654
  107. package/export/artifacts/@thesis/solidity-contracts/contracts/token/ERC20WithPermit.sol/ERC20WithPermit.json +2534 -2534
  108. package/export/artifacts/@thesis/solidity-contracts/contracts/token/MisfundRecovery.sol/MisfundRecovery.json +736 -736
  109. package/export/artifacts/contracts/bank/Bank.sol/Bank.json +1872 -1872
  110. package/export/artifacts/contracts/bridge/Bridge.sol/Bridge.json +7061 -7061
  111. package/export/artifacts/contracts/bridge/VendingMachine.sol/VendingMachine.json +1257 -1257
  112. package/export/artifacts/contracts/bridge/VendingMachineV2.sol/VendingMachineV2.json +972 -972
  113. package/export/artifacts/contracts/bridge/VendingMachineV3.sol/VendingMachineV3.json +1122 -1122
  114. package/export/artifacts/contracts/bridge/WalletCoordinator.sol/WalletCoordinator.json +5403 -5403
  115. package/export/artifacts/contracts/l2/L2TBTC.sol/L2TBTC.json +2961 -2961
  116. package/export/artifacts/contracts/l2/L2WormholeGateway.sol/L2WormholeGateway.json +3599 -4067
  117. package/export/artifacts/contracts/maintainer/MaintainerProxy.sol/MaintainerProxy.json +2393 -2393
  118. package/export/artifacts/contracts/relay/LightRelay.sol/LightRelay.json +1921 -1921
  119. package/export/artifacts/contracts/relay/LightRelayMaintainerProxy.sol/LightRelayMaintainerProxy.json +1013 -1013
  120. package/export/artifacts/contracts/test/BankStub.sol/BankStub.json +1874 -1874
  121. package/export/artifacts/contracts/test/BridgeStub.sol/BridgeStub.json +8094 -8094
  122. package/export/artifacts/contracts/test/GoerliLightRelay.sol/GoerliLightRelay.json +1923 -1923
  123. package/export/artifacts/contracts/test/HeartbeatStub.sol/HeartbeatStub.json +129 -129
  124. package/export/artifacts/contracts/test/LightRelayStub.sol/LightRelayStub.json +2046 -2046
  125. package/export/artifacts/contracts/test/ReceiveApprovalStub.sol/ReceiveApprovalStub.json +353 -353
  126. package/export/artifacts/contracts/test/SepoliaLightRelay.sol/SepoliaLightRelay.json +12024 -0
  127. package/export/artifacts/contracts/test/SystemTestRelay.sol/SystemTestRelay.json +568 -568
  128. package/export/artifacts/contracts/test/TestERC20.sol/TestERC20.json +2291 -2291
  129. package/export/artifacts/contracts/test/TestERC721.sol/TestERC721.json +1698 -1698
  130. package/export/artifacts/contracts/test/TestEcdsaLib.sol/TestEcdsaLib.json +189 -189
  131. package/export/artifacts/contracts/test/WormholeBridgeStub.sol/WormholeBridgeStub.json +1448 -1448
  132. package/export/artifacts/contracts/token/TBTC.sol/TBTC.json +2847 -2847
  133. package/export/artifacts/contracts/vault/DonationVault.sol/DonationVault.json +858 -858
  134. package/export/artifacts/contracts/vault/TBTCVault.sol/TBTCVault.json +3476 -3476
  135. package/export/deploy/01_deploy_light_relay.js +3 -0
  136. package/export/deploy/09_deploy_bridge_governance.js +4 -2
  137. package/export/deploy/19_authorize_spv_maintainer_in_bridge.js +3 -3
  138. package/export/deploy/24_transfer_tbtc_ownership.js +1 -1
  139. package/export/deploy/28_authorize_bridge_in_reimbursement_pool.js +1 -1
  140. package/export/deploy/40_authorize_light_relay_maintainer_proxy_in_reimbursement_pool.js +1 -1
  141. package/export/deploy/41_authorize_light_relay_maintainer_proxy_in_light_relay.js +7 -3
  142. package/export/hardhat.config.js +23 -0
  143. package/export/typechain/SepoliaLightRelay.js +2 -0
  144. package/export/typechain/factories/L2WormholeGateway__factory.js +1 -14
  145. package/export/typechain/factories/SepoliaLightRelay__factory.js +535 -0
  146. package/export/typechain/factories/WormholeBridgeStub__factory.js +1 -1
  147. package/export/typechain/index.js +3 -1
  148. package/package.json +3 -3
@@ -317,7 +317,7 @@
317
317
  "content": "// SPDX-License-Identifier: GPL-3.0-only\n\n// ██████████████ ▐████▌ ██████████████\n// ██████████████ ▐████▌ ██████████████\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ██████████████ ▐████▌ ██████████████\n// ██████████████ ▐████▌ ██████████████\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n\npragma solidity ^0.8.17;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\n\n/// @title L2TBTC\n/// @notice Canonical L2/sidechain token implementation. tBTC token is minted on\n/// L1 and locked there to be moved to L2/sidechain. By deploying\n/// a canonical token on each L2/sidechain, we can ensure the supply of\n/// tBTC remains sacrosanct, while enabling quick, interoperable\n/// cross-chain bridges and localizing ecosystem risk.\n///\n/// This contract is flexible enough to:\n/// - Delegate minting authority to a native bridge on the chain, if\n/// present.\n/// - Delegate minting authority to a short list of ecosystem bridges.\n/// - Have mints and burns paused by any one of n guardians, allowing\n/// avoidance of contagion in case of a chain- or bridge-specific\n/// incident.\n/// - Be governed and upgradeable.\n///\n/// The token is burnable by the token holder and supports EIP2612\n/// permits. Token holder can authorize a transfer of their token with\n/// a signature conforming EIP712 standard instead of an on-chain\n/// transaction from their address. Anyone can submit this signature on\n/// the user's behalf by calling the permit function, paying gas fees,\n/// and possibly performing other actions in the same transaction.\n/// The governance can recover ERC20 and ERC721 tokens sent mistakenly\n/// to L2TBTC token contract.\ncontract L2TBTC is\n ERC20Upgradeable,\n ERC20BurnableUpgradeable,\n ERC20PermitUpgradeable,\n OwnableUpgradeable,\n PausableUpgradeable\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Indicates if the given address is a minter. Only minters can\n /// mint the token.\n mapping(address => bool) public isMinter;\n\n /// @notice List of all minters.\n address[] public minters;\n\n /// @notice Indicates if the given address is a guardian. Only guardians can\n /// pause token mints and burns.\n mapping(address => bool) public isGuardian;\n\n /// @notice List of all guardians.\n address[] public guardians;\n\n event MinterAdded(address indexed minter);\n event MinterRemoved(address indexed minter);\n\n event GuardianAdded(address indexed guardian);\n event GuardianRemoved(address indexed guardian);\n\n modifier onlyMinter() {\n require(isMinter[msg.sender], \"Caller is not a minter\");\n _;\n }\n\n modifier onlyGuardian() {\n require(isGuardian[msg.sender], \"Caller is not a guardian\");\n _;\n }\n\n /// @notice Initializes the token contract.\n /// @param _name The name of the token.\n /// @param _symbol The symbol of the token, usually a shorter version of the\n /// name.\n function initialize(string memory _name, string memory _symbol)\n external\n initializer\n {\n // OpenZeppelin upgradeable contracts documentation says:\n //\n // \"Use with multiple inheritance requires special care. Initializer\n // functions are not linearized by the compiler like constructors.\n // Because of this, each __{ContractName}_init function embeds the\n // linearized calls to all parent initializers. As a consequence,\n // calling two of these init functions can potentially initialize the\n // same contract twice.\"\n //\n // Note that ERC20 extensions do not linearize calls to ERC20Upgradeable\n // initializer so we call all extension initializers individually. At\n // the same time, ERC20PermitUpgradeable does linearize the call to\n // EIP712Upgradeable so we are not using the unchained initializer\n // versions.\n __ERC20_init(_name, _symbol);\n __ERC20Burnable_init();\n __ERC20Permit_init(_name);\n __Ownable_init();\n __Pausable_init();\n }\n\n /// @notice Adds the address to the minters list.\n /// @dev Requirements:\n /// - The caller must be the contract owner.\n /// - `minter` must not be a minter address already.\n /// @param minter The address to be added as a minter.\n function addMinter(address minter) external onlyOwner {\n require(!isMinter[minter], \"This address is already a minter\");\n isMinter[minter] = true;\n minters.push(minter);\n emit MinterAdded(minter);\n }\n\n /// @notice Removes the address from the minters list.\n /// @dev Requirements:\n /// - The caller must be the contract owner.\n /// - `minter` must be a minter address.\n /// @param minter The address to be removed from the minters list.\n function removeMinter(address minter) external onlyOwner {\n require(isMinter[minter], \"This address is not a minter\");\n delete isMinter[minter];\n\n // We do not expect too many minters so a simple loop is safe.\n for (uint256 i = 0; i < minters.length; i++) {\n if (minters[i] == minter) {\n minters[i] = minters[minters.length - 1];\n // slither-disable-next-line costly-loop\n minters.pop();\n break;\n }\n }\n\n emit MinterRemoved(minter);\n }\n\n /// @notice Adds the address to the guardians list.\n /// @dev Requirements:\n /// - The caller must be the contract owner.\n /// - `guardian` must not be a guardian address already.\n /// @param guardian The address to be added as a guardian.\n function addGuardian(address guardian) external onlyOwner {\n require(!isGuardian[guardian], \"This address is already a guardian\");\n isGuardian[guardian] = true;\n guardians.push(guardian);\n emit GuardianAdded(guardian);\n }\n\n /// @notice Removes the address from the guardians list.\n /// @dev Requirements:\n /// - The caller must be the contract owner.\n /// - `guardian` must be a guardian address.\n /// @param guardian The address to be removed from the guardians list.\n function removeGuardian(address guardian) external onlyOwner {\n require(isGuardian[guardian], \"This address is not a guardian\");\n delete isGuardian[guardian];\n\n // We do not expect too many guardians so a simple loop is safe.\n for (uint256 i = 0; i < guardians.length; i++) {\n if (guardians[i] == guardian) {\n guardians[i] = guardians[guardians.length - 1];\n // slither-disable-next-line costly-loop\n guardians.pop();\n break;\n }\n }\n\n emit GuardianRemoved(guardian);\n }\n\n /// @notice Allows the governance of the token contract to recover any ERC20\n /// sent mistakenly to the token contract address.\n /// @param token The address of the token to be recovered.\n /// @param recipient The token recipient address that will receive recovered\n /// tokens.\n /// @param amount The amount to be recovered.\n function recoverERC20(\n IERC20Upgradeable token,\n address recipient,\n uint256 amount\n ) external onlyOwner {\n token.safeTransfer(recipient, amount);\n }\n\n /// @notice Allows the governance of the token contract to recover any\n /// ERC721 sent mistakenly to the token contract address.\n /// @param token The address of the token to be recovered.\n /// @param recipient The token recipient address that will receive the\n /// recovered token.\n /// @param tokenId The ID of the ERC721 token to be recovered.\n function recoverERC721(\n IERC721Upgradeable token,\n address recipient,\n uint256 tokenId,\n bytes calldata data\n ) external onlyOwner {\n token.safeTransferFrom(address(this), recipient, tokenId, data);\n }\n\n /// @notice Allows one of the guardians to pause mints and burns allowing\n /// avoidance of contagion in case of a chain- or bridge-specific\n /// incident.\n /// @dev Requirements:\n /// - The caller must be a guardian.\n /// - The contract must not be already paused.\n function pause() external onlyGuardian {\n _pause();\n }\n\n /// @notice Allows the governance to unpause mints and burns previously\n /// paused by one of the guardians.\n /// @dev Requirements:\n /// - The caller must be the contract owner.\n /// - The contract must be paused.\n function unpause() external onlyOwner {\n _unpause();\n }\n\n /// @notice Allows one of the minters to mint `amount` tokens and assign\n /// them to `account`, increasing the total supply. Emits\n /// a `Transfer` event with `from` set to the zero address.\n /// @dev Requirements:\n /// - The caller must be a minter.\n /// - `account` must not be the zero address.\n /// @param account The address to receive tokens.\n /// @param amount The amount of token to be minted.\n function mint(address account, uint256 amount)\n external\n whenNotPaused\n onlyMinter\n {\n _mint(account, amount);\n }\n\n /// @notice Destroys `amount` tokens from the caller. Emits a `Transfer`\n /// event with `to` set to the zero address.\n /// @dev Requirements:\n /// - The caller must have at least `amount` tokens.\n /// @param amount The amount of token to be burned.\n function burn(uint256 amount) public override whenNotPaused {\n super.burn(amount);\n }\n\n /// @notice Destroys `amount` tokens from `account`, deducting from the\n /// caller's allowance. Emits a `Transfer` event with `to` set to\n /// the zero address.\n /// @dev Requirements:\n /// - The che caller must have allowance for `accounts`'s tokens of at\n /// least `amount`.\n /// - `account` must not be the zero address.\n /// - `account` must have at least `amount` tokens.\n /// @param account The address owning tokens to be burned.\n /// @param amount The amount of token to be burned.\n function burnFrom(address account, uint256 amount)\n public\n override\n whenNotPaused\n {\n super.burnFrom(account, amount);\n }\n\n /// @notice Allows to fetch a list of all minters.\n function getMinters() external view returns (address[] memory) {\n return minters;\n }\n\n /// @notice Allows to fetch a list of all guardians.\n function getGuardians() external view returns (address[] memory) {\n return guardians;\n }\n}\n"
318
318
  },
319
319
  "contracts/l2/L2WormholeGateway.sol": {
320
- "content": "// SPDX-License-Identifier: GPL-3.0-only\n\n// ██████████████ ▐████▌ ██████████████\n// ██████████████ ▐████▌ ██████████████\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ██████████████ ▐████▌ ██████████████\n// ██████████████ ▐████▌ ██████████████\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n\npragma solidity ^0.8.17;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport \"./L2TBTC.sol\";\n\n/// @title IWormholeTokenBridge\n/// @notice Wormhole Token Bridge interface. Contains only selected functions\n/// used by L2WormholeGateway.\ninterface IWormholeTokenBridge {\n function completeTransferWithPayload(bytes memory encodedVm)\n external\n returns (bytes memory);\n\n function parseTransferWithPayload(bytes memory encoded)\n external\n pure\n returns (TransferWithPayload memory transfer);\n\n function transferTokens(\n address token,\n uint256 amount,\n uint16 recipientChain,\n bytes32 recipient,\n uint256 arbiterFee,\n uint32 nonce\n ) external payable returns (uint64 sequence);\n\n function transferTokensWithPayload(\n address token,\n uint256 amount,\n uint16 recipientChain,\n bytes32 recipient,\n uint32 nonce,\n bytes memory payload\n ) external payable returns (uint64 sequence);\n\n struct TransferWithPayload {\n uint8 payloadID;\n uint256 amount;\n bytes32 tokenAddress;\n uint16 tokenChain;\n bytes32 to;\n uint16 toChain;\n bytes32 fromAddress;\n bytes payload;\n }\n}\n\n/// @title L2WormholeGateway\n/// @notice Selected cross-ecosystem bridges are given the minting authority for\n/// tBTC token on L2 and sidechains. This contract gives a minting\n/// authority to the Wormhole Bridge.\n///\n/// The process of bridging from L1 to L2 (or sidechain) looks as\n/// follows:\n/// 1. There is a tBTC holder on L1. The holder goes to the Wormhole\n/// Portal and selects the chain they want to bridge to.\n/// 2. The holder submits one transaction to L1 locking their tBTC\n/// tokens in the bridge’s smart contract. After the transaction is\n/// mined, they wait about 15 minutes for the Ethereum block\n/// finality.\n/// 3. The holder submits one transaction to L2 that is minting tokens.\n/// After that transaction is mined, they have their tBTC on L2.\n///\n/// The process of bridging from L2 (or sidechain) to L1 looks as\n/// follows:\n/// 1. There is a tBTC holder on L2. That holder goes to the Wormhole\n/// Portal and selects one of the L2 chains they want to bridge from.\n/// 2. The holder submits one transaction to L2 that is burning the\n/// token. After the transaction is mined, they wait about 15 minutes\n/// for the L2 block finality.\n/// 3. The holder submits one transaction to L1 unlocking their tBTC\n/// tokens from the bridge’s smart contract. After that transaction\n/// is mined, they have their tBTC on L1.\n///\n/// This smart contract is integrated with step 3 of L1->L2 bridging and\n/// step 1 of L2->L1 or L2->L2 bridging. When the user redeems token on\n/// L2, this contract receives the Wormhole tBTC representation and\n/// mints the canonical tBTC in an equal amount. When user sends their\n/// token from L1, this contract burns the canonical tBTC and sends\n/// Wormhole tBTC representation through the bridge in an equal amount.\n/// @dev This contract is supposed to be deployed behind a transparent\n/// upgradeable proxy.\ncontract L2WormholeGateway is\n Initializable,\n OwnableUpgradeable,\n ReentrancyGuardUpgradeable\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Reference to the Wormhole Token Bridge contract.\n IWormholeTokenBridge public bridge;\n\n /// @notice Wormhole tBTC token representation.\n IERC20Upgradeable public bridgeToken;\n\n /// @notice Canonical tBTC token.\n L2TBTC public tbtc;\n\n /// @notice Maps Wormhole chain ID to the Wormhole tBTC gateway address on\n /// that chain. For example, this chain's ID should be mapped to\n /// this contract's address. If there is no Wormhole tBTC gateway\n /// address on the given chain, there is no entry in this mapping.\n /// The mapping holds addresses in a Wormhole-specific format, where\n /// Ethereum address is left-padded with zeros.\n mapping(uint16 => bytes32) public gateways;\n\n /// @notice Minting limit for this gateway. Useful for early days of testing\n /// the system. The gateway can not mint more canonical tBTC than\n /// this limit.\n uint256 public mintingLimit;\n\n /// @notice The amount of tBTC minted by this contract. tBTC burned by this\n /// contract decreases this amount.\n uint256 public mintedAmount;\n\n event WormholeTbtcReceived(address receiver, uint256 amount);\n\n event WormholeTbtcSent(\n uint256 amount,\n uint16 recipientChain,\n bytes32 gateway,\n bytes32 recipient,\n uint256 arbiterFee,\n uint32 nonce\n );\n\n event WormholeTbtcDeposited(address depositor, uint256 amount);\n\n event GatewayAddressUpdated(uint16 chainId, bytes32 gateway);\n\n event MintingLimitUpdated(uint256 mintingLimit);\n\n function initialize(\n IWormholeTokenBridge _bridge,\n IERC20Upgradeable _bridgeToken,\n L2TBTC _tbtc\n ) external initializer {\n __Ownable_init();\n __ReentrancyGuard_init();\n\n require(\n address(_bridge) != address(0),\n \"Wormhole bridge address must not be 0x0\"\n );\n require(\n address(_bridgeToken) != address(0),\n \"Bridge token address must not be 0x0\"\n );\n require(\n address(_tbtc) != address(0),\n \"L2TBTC token address must not be 0x0\"\n );\n\n bridge = _bridge;\n bridgeToken = _bridgeToken;\n tbtc = _tbtc;\n mintingLimit = type(uint256).max;\n }\n\n /// @notice This function is called when the user sends their token from L2.\n /// The contract burns the canonical tBTC from the user and sends\n /// wormhole tBTC representation over the bridge.\n /// Keep in mind that when multiple bridges receive a minting\n /// authority on the canonical tBTC, this function may not be able\n /// to send all amounts of tBTC through the Wormhole bridge. The\n /// capability of Wormhole Bridge to send tBTC from the chain is\n /// limited to the amount of tBTC bridged through Wormhole to that\n /// chain.\n /// @dev Requirements:\n /// - The sender must have at least `amount` of the canonical tBTC and\n /// it has to be approved for L2WormholeGateway.\n /// - The L2WormholeGateway must have at least `amount` of the wormhole\n /// tBTC.\n /// - The recipient must not be 0x0.\n /// - The amount to transfer must not be 0,\n /// - The amount to transfer must be >= 10^10 (1e18 precision).\n /// Depending if Wormhole tBTC gateway is registered on the target\n /// chain, this function uses transfer or transfer with payload over\n /// the Wormhole bridge.\n /// @param amount The amount of tBTC to be sent.\n /// @param recipientChain The Wormhole recipient chain ID.\n /// @param recipient The address of the recipient in the Wormhole format.\n /// @param arbiterFee The Wormhole arbiter fee. Ignored if sending\n /// tBTC to chain with Wormhole tBTC gateway.\n /// @param nonce The Wormhole nonce used to batch messages together.\n /// @return The Wormhole sequence number.\n function sendTbtc(\n uint256 amount,\n uint16 recipientChain,\n bytes32 recipient,\n uint256 arbiterFee,\n uint32 nonce\n ) external payable nonReentrant returns (uint64) {\n require(recipient != bytes32(0), \"0x0 recipient not allowed\");\n require(amount != 0, \"Amount must not be 0\");\n\n // Normalize the amount to bridge. The dust can not be bridged due to\n // the decimal shift in the Wormhole Bridge contract.\n amount = normalize(amount);\n\n // Check again after dropping the dust.\n require(amount != 0, \"Amount too low to bridge\");\n\n require(\n bridgeToken.balanceOf(address(this)) >= amount,\n \"Not enough wormhole tBTC in the gateway to bridge\"\n );\n\n bytes32 gateway = gateways[recipientChain];\n\n emit WormholeTbtcSent(\n amount,\n recipientChain,\n gateway,\n recipient,\n arbiterFee,\n nonce\n );\n\n mintedAmount -= amount;\n tbtc.burnFrom(msg.sender, amount);\n bridgeToken.safeApprove(address(bridge), amount);\n\n if (gateway == bytes32(0)) {\n // No Wormhole tBTC gateway on the target chain. The token minted\n // by Wormhole should be considered canonical.\n return\n bridge.transferTokens{value: msg.value}(\n address(bridgeToken),\n amount,\n recipientChain,\n recipient,\n arbiterFee,\n nonce\n );\n } else {\n // There is a Wormhole tBTC gateway on the target chain.\n // The gateway needs to mint canonical tBTC for the recipient\n // encoded in the payload.\n return\n bridge.transferTokensWithPayload{value: msg.value}(\n address(bridgeToken),\n amount,\n recipientChain,\n gateway,\n nonce,\n abi.encode(recipient)\n );\n }\n }\n\n /// @notice This function is called when the user redeems their token on L2.\n /// The contract receives Wormhole tBTC representation and mints the\n /// canonical tBTC for the user.\n /// If the tBTC minting limit has been reached by this contract,\n /// instead of minting tBTC the receiver address receives Wormhole\n /// tBTC representation.\n /// @dev Requirements:\n /// - The receiver of Wormhole tBTC should be the L2WormholeGateway\n /// contract.\n /// - The receiver of the canonical tBTC should be abi-encoded in the\n /// payload.\n /// - The receiver of the canonical tBTC must not be the zero address.\n /// The Wormhole Token Bridge contract has protection against redeeming\n /// the same VAA again. When a Token Bridge VAA is redeemed, its\n /// message body hash is stored in a map. This map is used to check\n /// whether the hash has already been set in this map. For this reason,\n /// this function does not have to be nonReentrant.\n /// @param encodedVm A byte array containing a Wormhole VAA signed by the\n /// guardians.\n function receiveTbtc(bytes calldata encodedVm) external {\n // ITokenBridge.completeTransferWithPayload completes a contract-controlled\n // transfer of an ERC20 token. Calling this function is not enough to\n // ensure L2WormholeGateway received Wormhole tBTC representation.\n // Instead of going too deep into the ITokenBridge implementation,\n // asserting who is the receiver of the token, and which token it is,\n // we check the balance before the ITokenBridge call and the balance\n // after ITokenBridge call. This way, we are sure this contract received\n // Wormhole tBTC token in the given amount. This is transparent to\n // all potential upgrades of ITokenBridge implementation and no other\n // validations are needed.\n uint256 balanceBefore = bridgeToken.balanceOf(address(this));\n bytes memory encoded = bridge.completeTransferWithPayload(encodedVm);\n uint256 balanceAfter = bridgeToken.balanceOf(address(this));\n\n uint256 amount = balanceAfter - balanceBefore;\n // Protect against the custody of irrelevant tokens.\n require(amount > 0, \"No tBTC transferred\");\n\n address receiver = fromWormholeAddress(\n bytes32(bridge.parseTransferWithPayload(encoded).payload)\n );\n require(receiver != address(0), \"0x0 receiver not allowed\");\n\n // We send wormhole tBTC OR mint canonical tBTC. We do not want to send\n // dust. Sending wormhole tBTC is an exceptional situation and we want\n // to keep it simple.\n if (mintedAmount + amount > mintingLimit) {\n bridgeToken.safeTransfer(receiver, amount);\n } else {\n // The function is non-reentrant given bridge.completeTransferWithPayload\n // call that does not allow to use the same VAA again.\n // slither-disable-next-line reentrancy-benign\n mintedAmount += amount;\n tbtc.mint(receiver, amount);\n }\n\n // The function is non-reentrant given bridge.completeTransferWithPayload\n // call that does not allow to use the same VAA again.\n // slither-disable-next-line reentrancy-events\n emit WormholeTbtcReceived(receiver, amount);\n }\n\n /// @notice Allows to deposit Wormhole tBTC token in exchange for canonical\n /// tBTC. Useful in a situation when user received wormhole tBTC\n /// instead of canonical tBTC. One example of such situation is\n /// when the minting limit was exceeded but the user minted anyway.\n /// @dev Requirements:\n /// - The sender must have at least `amount` of the Wormhole tBTC and\n /// it has to be approved for L2WormholeGateway.\n /// - The minting limit must allow for minting the given amount.\n /// @param amount The amount of Wormhole tBTC to deposit.\n function depositWormholeTbtc(uint256 amount) external {\n require(\n mintedAmount + amount <= mintingLimit,\n \"Minting limit exceeded\"\n );\n\n emit WormholeTbtcDeposited(msg.sender, amount);\n mintedAmount += amount;\n bridgeToken.safeTransferFrom(msg.sender, address(this), amount);\n tbtc.mint(msg.sender, amount);\n }\n\n /// @notice Lets the governance to update the tBTC gateway address on the\n /// chain with the given Wormhole ID.\n /// @dev Use toWormholeAddress function to convert between Ethereum and\n /// Wormhole address formats.\n /// @param chainId Wormhole ID of the chain.\n /// @param gateway Address of tBTC gateway on the given chain in a Wormhole\n /// format.\n function updateGatewayAddress(uint16 chainId, bytes32 gateway)\n external\n onlyOwner\n {\n gateways[chainId] = gateway;\n emit GatewayAddressUpdated(chainId, gateway);\n }\n\n /// @notice Lets the governance to update the tBTC minting limit for this\n /// contract.\n /// @param _mintingLimit The new minting limit.\n function updateMintingLimit(uint256 _mintingLimit) external onlyOwner {\n mintingLimit = _mintingLimit;\n emit MintingLimitUpdated(_mintingLimit);\n }\n\n /// @notice Converts Ethereum address into Wormhole format.\n /// @param _address The address to convert.\n function toWormholeAddress(address _address)\n external\n pure\n returns (bytes32)\n {\n return bytes32(uint256(uint160(_address)));\n }\n\n /// @notice Converts Wormhole address into Ethereum format.\n /// @param _address The address to convert.\n function fromWormholeAddress(bytes32 _address)\n public\n pure\n returns (address)\n {\n return address(uint160(uint256(_address)));\n }\n\n /// @dev Eliminates the dust that cannot be bridged with Wormhole\n /// due to the decimal shift in the Wormhole Bridge contract.\n /// See https://github.com/wormhole-foundation/wormhole/blob/96682bdbeb7c87bfa110eade0554b3d8cbf788d2/ethereum/contracts/bridge/Bridge.sol#L276-L288\n function normalize(uint256 amount) internal pure returns (uint256) {\n // slither-disable-next-line divide-before-multiply\n amount /= 10**10;\n amount *= 10**10;\n return amount;\n }\n}\n"
320
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\n\n// ██████████████ ▐████▌ ██████████████\n// ██████████████ ▐████▌ ██████████████\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ██████████████ ▐████▌ ██████████████\n// ██████████████ ▐████▌ ██████████████\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n\npragma solidity ^0.8.17;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport \"./L2TBTC.sol\";\n\n/// @title IWormholeTokenBridge\n/// @notice Wormhole Token Bridge interface. Contains only selected functions\n/// used by L2WormholeGateway.\ninterface IWormholeTokenBridge {\n function completeTransferWithPayload(bytes memory encodedVm)\n external\n returns (bytes memory);\n\n function parseTransferWithPayload(bytes memory encoded)\n external\n pure\n returns (TransferWithPayload memory transfer);\n\n function transferTokens(\n address token,\n uint256 amount,\n uint16 recipientChain,\n bytes32 recipient,\n uint256 arbiterFee,\n uint32 nonce\n ) external payable returns (uint64 sequence);\n\n function transferTokensWithPayload(\n address token,\n uint256 amount,\n uint16 recipientChain,\n bytes32 recipient,\n uint32 nonce,\n bytes memory payload\n ) external payable returns (uint64 sequence);\n\n struct TransferWithPayload {\n uint8 payloadID;\n uint256 amount;\n bytes32 tokenAddress;\n uint16 tokenChain;\n bytes32 to;\n uint16 toChain;\n bytes32 fromAddress;\n bytes payload;\n }\n}\n\n/// @title L2WormholeGateway\n/// @notice Selected cross-ecosystem bridges are given the minting authority for\n/// tBTC token on L2 and sidechains. This contract gives a minting\n/// authority to the Wormhole Bridge.\n///\n/// The process of bridging from L1 to L2 (or sidechain) looks as\n/// follows:\n/// 1. There is a tBTC holder on L1. The holder goes to the Wormhole\n/// Portal and selects the chain they want to bridge to.\n/// 2. The holder submits one transaction to L1 locking their tBTC\n/// tokens in the bridge’s smart contract. After the transaction is\n/// mined, they wait about 15 minutes for the Ethereum block\n/// finality.\n/// 3. The holder submits one transaction to L2 that is minting tokens.\n/// After that transaction is mined, they have their tBTC on L2.\n///\n/// The process of bridging from L2 (or sidechain) to L1 looks as\n/// follows:\n/// 1. There is a tBTC holder on L2. That holder goes to the Wormhole\n/// Portal and selects one of the L2 chains they want to bridge from.\n/// 2. The holder submits one transaction to L2 that is burning the\n/// token. After the transaction is mined, they wait about 15 minutes\n/// for the L2 block finality.\n/// 3. The holder submits one transaction to L1 unlocking their tBTC\n/// tokens from the bridge’s smart contract. After that transaction\n/// is mined, they have their tBTC on L1.\n///\n/// This smart contract is integrated with step 3 of L1->L2 bridging and\n/// step 1 of L2->L1 or L2->L2 bridging. When the user redeems token on\n/// L2, this contract receives the Wormhole tBTC representation and\n/// mints the canonical tBTC in an equal amount. When user sends their\n/// token from L1, this contract burns the canonical tBTC and sends\n/// Wormhole tBTC representation through the bridge in an equal amount.\n/// @dev This contract is supposed to be deployed behind a transparent\n/// upgradeable proxy.\ncontract L2WormholeGateway is\n Initializable,\n OwnableUpgradeable,\n ReentrancyGuardUpgradeable\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Reference to the Wormhole Token Bridge contract.\n IWormholeTokenBridge public bridge;\n\n /// @notice Wormhole tBTC token representation.\n IERC20Upgradeable public bridgeToken;\n\n /// @notice Canonical tBTC token.\n L2TBTC public tbtc;\n\n /// @notice Maps Wormhole chain ID to the Wormhole tBTC gateway address on\n /// that chain. For example, this chain's ID should be mapped to\n /// this contract's address. If there is no Wormhole tBTC gateway\n /// address on the given chain, there is no entry in this mapping.\n /// The mapping holds addresses in a Wormhole-specific format, where\n /// Ethereum address is left-padded with zeros.\n mapping(uint16 => bytes32) public gateways;\n\n /// @notice Minting limit for this gateway. Useful for early days of testing\n /// the system. The gateway can not mint more canonical tBTC than\n /// this limit.\n uint256 public mintingLimit;\n\n /// @notice The amount of tBTC minted by this contract. tBTC burned by this\n /// contract decreases this amount.\n uint256 public mintedAmount;\n\n event WormholeTbtcReceived(address receiver, uint256 amount);\n\n event WormholeTbtcSent(\n uint256 amount,\n uint16 recipientChain,\n bytes32 gateway,\n bytes32 recipient,\n uint256 arbiterFee,\n uint32 nonce\n );\n\n event WormholeTbtcDeposited(address depositor, uint256 amount);\n\n event GatewayAddressUpdated(uint16 chainId, bytes32 gateway);\n\n event MintingLimitUpdated(uint256 mintingLimit);\n\n function initialize(\n IWormholeTokenBridge _bridge,\n IERC20Upgradeable _bridgeToken,\n L2TBTC _tbtc\n ) external initializer {\n __Ownable_init();\n __ReentrancyGuard_init();\n\n require(\n address(_bridge) != address(0),\n \"Wormhole bridge address must not be 0x0\"\n );\n require(\n address(_bridgeToken) != address(0),\n \"Bridge token address must not be 0x0\"\n );\n require(\n address(_tbtc) != address(0),\n \"L2TBTC token address must not be 0x0\"\n );\n\n bridge = _bridge;\n bridgeToken = _bridgeToken;\n tbtc = _tbtc;\n mintingLimit = type(uint256).max;\n }\n\n /// @notice This function is called when the user sends their token from L2.\n /// The contract burns the canonical tBTC from the user and sends\n /// wormhole tBTC representation over the bridge.\n /// Keep in mind that when multiple bridges receive a minting\n /// authority on the canonical tBTC, this function may not be able\n /// to send all amounts of tBTC through the Wormhole bridge. The\n /// capability of Wormhole Bridge to send tBTC from the chain is\n /// limited to the amount of tBTC bridged through Wormhole to that\n /// chain.\n /// @dev Requirements:\n /// - The sender must have at least `amount` of the canonical tBTC and\n /// it has to be approved for L2WormholeGateway.\n /// - The L2WormholeGateway must have at least `amount` of the wormhole\n /// tBTC.\n /// - The recipient must not be 0x0.\n /// - The amount to transfer must not be 0,\n /// - The amount to transfer must be >= 10^10 (1e18 precision).\n /// Depending if Wormhole tBTC gateway is registered on the target\n /// chain, this function uses transfer or transfer with payload over\n /// the Wormhole bridge.\n /// @param amount The amount of tBTC to be sent.\n /// @param recipientChain The Wormhole recipient chain ID.\n /// @param recipient The address of the recipient in the Wormhole format.\n /// @param arbiterFee The Wormhole arbiter fee. Ignored if sending\n /// tBTC to chain with Wormhole tBTC gateway.\n /// @param nonce The Wormhole nonce used to batch messages together.\n /// @return The Wormhole sequence number.\n function sendTbtc(\n uint256 amount,\n uint16 recipientChain,\n bytes32 recipient,\n uint256 arbiterFee,\n uint32 nonce\n ) external payable nonReentrant returns (uint64) {\n require(recipient != bytes32(0), \"0x0 recipient not allowed\");\n require(amount != 0, \"Amount must not be 0\");\n\n // Normalize the amount to bridge. The dust can not be bridged due to\n // the decimal shift in the Wormhole Bridge contract.\n amount = normalize(amount);\n\n // Check again after dropping the dust.\n require(amount != 0, \"Amount too low to bridge\");\n\n require(\n bridgeToken.balanceOf(address(this)) >= amount,\n \"Not enough wormhole tBTC in the gateway to bridge\"\n );\n\n bytes32 gateway = gateways[recipientChain];\n\n emit WormholeTbtcSent(\n amount,\n recipientChain,\n gateway,\n recipient,\n arbiterFee,\n nonce\n );\n\n mintedAmount -= amount;\n tbtc.burnFrom(msg.sender, amount);\n bridgeToken.safeApprove(address(bridge), amount);\n\n if (gateway == bytes32(0)) {\n // No Wormhole tBTC gateway on the target chain. The token minted\n // by Wormhole should be considered canonical.\n return\n bridge.transferTokens{value: msg.value}(\n address(bridgeToken),\n amount,\n recipientChain,\n recipient,\n arbiterFee,\n nonce\n );\n } else {\n // There is a Wormhole tBTC gateway on the target chain.\n // The gateway needs to mint canonical tBTC for the recipient\n // encoded in the payload.\n return\n bridge.transferTokensWithPayload{value: msg.value}(\n address(bridgeToken),\n amount,\n recipientChain,\n gateway,\n nonce,\n abi.encode(recipient)\n );\n }\n }\n\n /// @notice This function is called when the user redeems their token on L2.\n /// The contract receives Wormhole tBTC representation and mints the\n /// canonical tBTC for the user.\n /// If the tBTC minting limit has been reached by this contract,\n /// instead of minting tBTC the receiver address receives Wormhole\n /// tBTC representation.\n /// @dev Requirements:\n /// - The receiver of Wormhole tBTC should be the L2WormholeGateway\n /// contract.\n /// - The receiver of the canonical tBTC should be abi-encoded in the\n /// payload.\n /// - The receiver of the canonical tBTC must not be the zero address.\n ///\n /// The Wormhole Token Bridge contract has protection against redeeming\n /// the same VAA again. When a Token Bridge VAA is redeemed, its\n /// message body hash is stored in a map. This map is used to check\n /// whether the hash has already been set in this map. For this reason,\n /// this function does not have to be nonReentrant in theory. However,\n /// to make this function non-dependent on Wormhole Bridge implementation,\n /// we are making it nonReentrant anyway.\n /// @param encodedVm A byte array containing a Wormhole VAA signed by the\n /// guardians.\n function receiveTbtc(bytes calldata encodedVm) external nonReentrant {\n // ITokenBridge.completeTransferWithPayload completes a contract-controlled\n // transfer of an ERC20 token. Calling this function is not enough to\n // ensure L2WormholeGateway received Wormhole tBTC representation.\n // Instead of going too deep into the ITokenBridge implementation,\n // asserting who is the receiver of the token, and which token it is,\n // we check the balance before the ITokenBridge call and the balance\n // after ITokenBridge call. This way, we are sure this contract received\n // Wormhole tBTC token in the given amount. This is transparent to\n // all potential upgrades of ITokenBridge implementation and no other\n // validations are needed.\n uint256 balanceBefore = bridgeToken.balanceOf(address(this));\n bytes memory encoded = bridge.completeTransferWithPayload(encodedVm);\n uint256 balanceAfter = bridgeToken.balanceOf(address(this));\n\n uint256 amount = balanceAfter - balanceBefore;\n // Protect against the custody of irrelevant tokens.\n require(amount > 0, \"No tBTC transferred\");\n\n address receiver = fromWormholeAddress(\n bytes32(bridge.parseTransferWithPayload(encoded).payload)\n );\n require(receiver != address(0), \"0x0 receiver not allowed\");\n\n // We send wormhole tBTC OR mint canonical tBTC. We do not want to send\n // dust. Sending wormhole tBTC is an exceptional situation and we want\n // to keep it simple.\n if (mintedAmount + amount > mintingLimit) {\n bridgeToken.safeTransfer(receiver, amount);\n } else {\n // The function is non-reentrant.\n // slither-disable-next-line reentrancy-benign\n mintedAmount += amount;\n tbtc.mint(receiver, amount);\n }\n\n // The function is non-reentrant.\n // slither-disable-next-line reentrancy-events\n emit WormholeTbtcReceived(receiver, amount);\n }\n\n /// @notice Lets the governance to update the tBTC gateway address on the\n /// chain with the given Wormhole ID.\n /// @dev Use toWormholeAddress function to convert between Ethereum and\n /// Wormhole address formats.\n /// @param chainId Wormhole ID of the chain.\n /// @param gateway Address of tBTC gateway on the given chain in a Wormhole\n /// format.\n function updateGatewayAddress(uint16 chainId, bytes32 gateway)\n external\n onlyOwner\n {\n gateways[chainId] = gateway;\n emit GatewayAddressUpdated(chainId, gateway);\n }\n\n /// @notice Lets the governance to update the tBTC minting limit for this\n /// contract.\n /// @param _mintingLimit The new minting limit.\n function updateMintingLimit(uint256 _mintingLimit) external onlyOwner {\n mintingLimit = _mintingLimit;\n emit MintingLimitUpdated(_mintingLimit);\n }\n\n /// @notice Converts Ethereum address into Wormhole format.\n /// @param _address The address to convert.\n function toWormholeAddress(address _address)\n external\n pure\n returns (bytes32)\n {\n return bytes32(uint256(uint160(_address)));\n }\n\n /// @notice Converts Wormhole address into Ethereum format.\n /// @param _address The address to convert.\n function fromWormholeAddress(bytes32 _address)\n public\n pure\n returns (address)\n {\n return address(uint160(uint256(_address)));\n }\n\n /// @dev Eliminates the dust that cannot be bridged with Wormhole\n /// due to the decimal shift in the Wormhole Bridge contract.\n /// See https://github.com/wormhole-foundation/wormhole/blob/96682bdbeb7c87bfa110eade0554b3d8cbf788d2/ethereum/contracts/bridge/Bridge.sol#L276-L288\n function normalize(uint256 amount) internal pure returns (uint256) {\n // slither-disable-next-line divide-before-multiply\n amount /= 10**10;\n amount *= 10**10;\n return amount;\n }\n}\n"
321
321
  },
322
322
  "contracts/maintainer/MaintainerProxy.sol": {
323
323
  "content": "// SPDX-License-Identifier: GPL-3.0-only\n\n// ██████████████ ▐████▌ ██████████████\n// ██████████████ ▐████▌ ██████████████\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ██████████████ ▐████▌ ██████████████\n// ██████████████ ▐████▌ ██████████████\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@keep-network/random-beacon/contracts/Reimbursable.sol\";\nimport \"@keep-network/random-beacon/contracts/ReimbursementPool.sol\";\n\nimport \"../bridge/BitcoinTx.sol\";\nimport \"../bridge/Bridge.sol\";\n\n/// @title Maintainer Proxy\n/// @notice Maintainers are the willing off-chain clients approved by the governance.\n/// Maintainers proxy calls to the `Bridge` contract via 'MaintainerProxy'\n/// and are refunded for the spent gas from the `ReimbursementPool`.\n/// There are two types of maintainers: wallet maintainers and SPV\n/// maintainers.\ncontract MaintainerProxy is Ownable, Reimbursable {\n Bridge public bridge;\n\n /// @notice Authorized wallet maintainers that can interact with the set of\n /// functions for wallet maintainers only. Authorization can be\n /// granted and removed by the governance.\n /// @dev 'Key' is the address of the maintainer. 'Value' represents an index+1\n /// in the 'maintainers' array. 1 was added so the maintainer index can\n /// never be 0 which is a reserved index for a non-existent maintainer\n /// in this map.\n mapping(address => uint256) public isWalletMaintainer;\n\n /// @notice This list of wallet maintainers keeps the order of which wallet\n /// maintainer should be submitting a next transaction. It does not\n /// enforce the order but only tracks who should be next in line.\n address[] public walletMaintainers;\n\n /// @notice Authorized SPV maintainers that can interact with the set of\n /// functions for SPV maintainers only. Authorization can be\n /// granted and removed by the governance.\n /// @dev 'Key' is the address of the maintainer. 'Value' represents an index+1\n /// in the 'maintainers' array. 1 was added so the maintainer index can\n /// never be 0 which is a reserved index for a non-existent maintainer\n /// in this map.\n mapping(address => uint256) public isSpvMaintainer;\n\n /// @notice This list of SPV maintainers keeps the order of which SPV\n /// maintainer should be submitting a next transaction. It does not\n /// enforce the order but only tracks who should be next in line.\n address[] public spvMaintainers;\n\n /// @notice Gas that is meant to balance the submission of deposit sweep proof\n /// overall cost. Can be updated by the governance based on the current\n /// market conditions.\n uint256 public submitDepositSweepProofGasOffset;\n\n /// @notice Gas that is meant to balance the submission of redemption proof\n /// overall cost. Can be updated by the governance based on the current\n /// market conditions.\n uint256 public submitRedemptionProofGasOffset;\n\n /// @notice Gas that is meant to balance the reset of moving funds timeout\n /// overall cost. Can be updated by the governance based on the current\n /// market conditions.\n uint256 public resetMovingFundsTimeoutGasOffset;\n\n /// @notice Gas that is meant to balance the submission of moving funds proof\n /// overall cost. Can be updated by the governance based on the current\n /// market conditions.\n uint256 public submitMovingFundsProofGasOffset;\n\n /// @notice Gas that is meant to balance the notification of moving funds below\n /// dust overall cost. Can be updated by the governance based on the\n /// current market conditions.\n uint256 public notifyMovingFundsBelowDustGasOffset;\n\n /// @notice Gas that is meant to balance the submission of moved funds sweep\n /// proof overall cost. Can be updated by the governance based on the\n /// current market conditions.\n uint256 public submitMovedFundsSweepProofGasOffset;\n\n /// @notice Gas that is meant to balance the request of a new wallet overall\n /// cost. Can be updated by the governance based on the current\n /// market conditions.\n uint256 public requestNewWalletGasOffset;\n\n /// @notice Gas that is meant to balance the notification of closeable wallet\n /// overall cost. Can be updated by the governance based on the current\n /// market conditions.\n uint256 public notifyWalletCloseableGasOffset;\n\n /// @notice Gas that is meant to balance the notification of wallet closing\n /// period elapsed overall cost. Can be updated by the governance\n /// based on the current market conditions.\n uint256 public notifyWalletClosingPeriodElapsedGasOffset;\n\n /// @notice Gas that is meant to balance the defeat fraud challenge\n /// overall cost. Can be updated by the governance based on the current\n /// market conditions.\n uint256 public defeatFraudChallengeGasOffset;\n\n /// @notice Gas that is meant to balance the defeat fraud challenge with heartbeat\n /// overall cost. Can be updated by the governance based on the current\n /// market conditions.\n uint256 public defeatFraudChallengeWithHeartbeatGasOffset;\n\n event WalletMaintainerAuthorized(address indexed maintainer);\n\n event WalletMaintainerUnauthorized(address indexed maintainer);\n\n event SpvMaintainerAuthorized(address indexed maintainer);\n\n event SpvMaintainerUnauthorized(address indexed maintainer);\n\n event BridgeUpdated(address newBridge);\n\n event GasOffsetParametersUpdated(\n uint256 submitDepositSweepProofGasOffset,\n uint256 submitRedemptionProofGasOffset,\n uint256 resetMovingFundsTimeoutGasOffset,\n uint256 submitMovingFundsProofGasOffset,\n uint256 notifyMovingFundsBelowDustGasOffset,\n uint256 submitMovedFundsSweepProofGasOffset,\n uint256 requestNewWalletGasOffset,\n uint256 notifyWalletCloseableGasOffset,\n uint256 notifyWalletClosingPeriodElapsedGasOffset,\n uint256 defeatFraudChallengeGasOffset,\n uint256 defeatFraudChallengeWithHeartbeatGasOffset\n );\n\n modifier onlyWalletMaintainer() {\n require(\n isWalletMaintainer[msg.sender] != 0,\n \"Caller is not authorized\"\n );\n _;\n }\n\n modifier onlySpvMaintainer() {\n require(isSpvMaintainer[msg.sender] != 0, \"Caller is not authorized\");\n _;\n }\n\n modifier onlyReimbursableAdmin() override {\n require(owner() == msg.sender, \"Caller is not the owner\");\n _;\n }\n\n constructor(Bridge _bridge, ReimbursementPool _reimbursementPool) {\n bridge = _bridge;\n reimbursementPool = _reimbursementPool;\n submitDepositSweepProofGasOffset = 27000;\n submitRedemptionProofGasOffset = 0;\n resetMovingFundsTimeoutGasOffset = 1000;\n submitMovingFundsProofGasOffset = 15000;\n notifyMovingFundsBelowDustGasOffset = 3500;\n submitMovedFundsSweepProofGasOffset = 22000;\n requestNewWalletGasOffset = 3500;\n notifyWalletCloseableGasOffset = 4000;\n notifyWalletClosingPeriodElapsedGasOffset = 3000;\n defeatFraudChallengeGasOffset = 10000;\n defeatFraudChallengeWithHeartbeatGasOffset = 5000;\n }\n\n /// @notice Wraps `Bridge.submitDepositSweepProof` call and reimburses the\n /// caller's transaction cost.\n /// @dev See `Bridge.submitDepositSweepProof` function documentation.\n function submitDepositSweepProof(\n BitcoinTx.Info calldata sweepTx,\n BitcoinTx.Proof calldata sweepProof,\n BitcoinTx.UTXO calldata mainUtxo,\n address vault\n ) external onlySpvMaintainer {\n uint256 gasStart = gasleft();\n\n bridge.submitDepositSweepProof(sweepTx, sweepProof, mainUtxo, vault);\n\n reimbursementPool.refund(\n (gasStart - gasleft()) + submitDepositSweepProofGasOffset,\n msg.sender\n );\n }\n\n /// @notice Wraps `Bridge.submitRedemptionProof` call and reimburses the\n /// caller's transaction cost.\n /// @dev See `Bridge.submitRedemptionProof` function documentation.\n function submitRedemptionProof(\n BitcoinTx.Info calldata redemptionTx,\n BitcoinTx.Proof calldata redemptionProof,\n BitcoinTx.UTXO calldata mainUtxo,\n bytes20 walletPubKeyHash\n ) external onlySpvMaintainer {\n uint256 gasStart = gasleft();\n\n bridge.submitRedemptionProof(\n redemptionTx,\n redemptionProof,\n mainUtxo,\n walletPubKeyHash\n );\n\n reimbursementPool.refund(\n (gasStart - gasleft()) + submitRedemptionProofGasOffset,\n msg.sender\n );\n }\n\n /// @notice Wraps `Bridge.resetMovingFundsTimeout` call and reimburses the\n /// caller's transaction cost.\n /// @dev See `Bridge.resetMovingFundsTimeout` function documentation.\n function resetMovingFundsTimeout(bytes20 walletPubKeyHash) external {\n uint256 gasStart = gasleft();\n\n bridge.resetMovingFundsTimeout(walletPubKeyHash);\n\n reimbursementPool.refund(\n (gasStart - gasleft()) + resetMovingFundsTimeoutGasOffset,\n msg.sender\n );\n }\n\n /// @notice Wraps `Bridge.submitMovingFundsProof` call and reimburses the\n /// caller's transaction cost.\n /// @dev See `Bridge.submitMovingFundsProof` function documentation.\n function submitMovingFundsProof(\n BitcoinTx.Info calldata movingFundsTx,\n BitcoinTx.Proof calldata movingFundsProof,\n BitcoinTx.UTXO calldata mainUtxo,\n bytes20 walletPubKeyHash\n ) external onlySpvMaintainer {\n uint256 gasStart = gasleft();\n\n bridge.submitMovingFundsProof(\n movingFundsTx,\n movingFundsProof,\n mainUtxo,\n walletPubKeyHash\n );\n\n reimbursementPool.refund(\n (gasStart - gasleft()) + submitMovingFundsProofGasOffset,\n msg.sender\n );\n }\n\n /// @notice Wraps `Bridge.notifyMovingFundsBelowDust` call and reimburses the\n /// caller's transaction cost.\n /// @dev See `Bridge.notifyMovingFundsBelowDust` function documentation.\n function notifyMovingFundsBelowDust(\n bytes20 walletPubKeyHash,\n BitcoinTx.UTXO calldata mainUtxo\n ) external onlyWalletMaintainer {\n uint256 gasStart = gasleft();\n\n bridge.notifyMovingFundsBelowDust(walletPubKeyHash, mainUtxo);\n\n reimbursementPool.refund(\n (gasStart - gasleft()) + notifyMovingFundsBelowDustGasOffset,\n msg.sender\n );\n }\n\n /// @notice Wraps `Bridge.submitMovedFundsSweepProof` call and reimburses the\n /// caller's transaction cost.\n /// @dev See `Bridge.submitMovedFundsSweepProof` function documentation.\n function submitMovedFundsSweepProof(\n BitcoinTx.Info calldata sweepTx,\n BitcoinTx.Proof calldata sweepProof,\n BitcoinTx.UTXO calldata mainUtxo\n ) external onlySpvMaintainer {\n uint256 gasStart = gasleft();\n\n bridge.submitMovedFundsSweepProof(sweepTx, sweepProof, mainUtxo);\n\n reimbursementPool.refund(\n (gasStart - gasleft()) + submitMovedFundsSweepProofGasOffset,\n msg.sender\n );\n }\n\n /// @notice Wraps `Bridge.requestNewWallet` call and reimburses the\n /// caller's transaction cost.\n /// @dev See `Bridge.requestNewWallet` function documentation.\n function requestNewWallet(BitcoinTx.UTXO calldata activeWalletMainUtxo)\n external\n onlyWalletMaintainer\n {\n uint256 gasStart = gasleft();\n\n bridge.requestNewWallet(activeWalletMainUtxo);\n\n reimbursementPool.refund(\n (gasStart - gasleft()) + requestNewWalletGasOffset,\n msg.sender\n );\n }\n\n /// @notice Wraps `Bridge.notifyWalletCloseable` call and reimburses the\n /// caller's transaction cost.\n /// @dev See `Bridge.notifyWalletCloseable` function documentation.\n function notifyWalletCloseable(\n bytes20 walletPubKeyHash,\n BitcoinTx.UTXO calldata walletMainUtxo\n ) external onlyWalletMaintainer {\n uint256 gasStart = gasleft();\n\n bridge.notifyWalletCloseable(walletPubKeyHash, walletMainUtxo);\n\n reimbursementPool.refund(\n (gasStart - gasleft()) + notifyWalletCloseableGasOffset,\n msg.sender\n );\n }\n\n /// @notice Wraps `Bridge.notifyWalletClosingPeriodElapsed` call and reimburses\n /// the caller's transaction cost.\n /// @dev See `Bridge.notifyWalletClosingPeriodElapsed` function documentation.\n function notifyWalletClosingPeriodElapsed(bytes20 walletPubKeyHash)\n external\n onlyWalletMaintainer\n {\n uint256 gasStart = gasleft();\n\n bridge.notifyWalletClosingPeriodElapsed(walletPubKeyHash);\n\n reimbursementPool.refund(\n (gasStart - gasleft()) + notifyWalletClosingPeriodElapsedGasOffset,\n msg.sender\n );\n }\n\n /// @notice Wraps `Bridge.defeatFraudChallenge` call and reimburses the\n /// caller's transaction cost.\n /// @dev See `Bridge.defeatFraudChallenge` function documentation.\n function defeatFraudChallenge(\n bytes calldata walletPublicKey,\n bytes calldata preimage,\n bool witness\n ) external {\n uint256 gasStart = gasleft();\n\n bridge.defeatFraudChallenge(walletPublicKey, preimage, witness);\n\n reimbursementPool.refund(\n (gasStart - gasleft()) + defeatFraudChallengeGasOffset,\n msg.sender\n );\n }\n\n /// @notice Wraps `Bridge.defeatFraudChallengeWithHeartbeat` call and\n /// reimburses the caller's transaction cost.\n /// @dev See `Bridge.defeatFraudChallengeWithHeartbeat` function documentation.\n function defeatFraudChallengeWithHeartbeat(\n bytes calldata walletPublicKey,\n bytes calldata heartbeatMessage\n ) external {\n uint256 gasStart = gasleft();\n\n bridge.defeatFraudChallengeWithHeartbeat(\n walletPublicKey,\n heartbeatMessage\n );\n\n reimbursementPool.refund(\n (gasStart - gasleft()) + defeatFraudChallengeWithHeartbeatGasOffset,\n msg.sender\n );\n }\n\n /// @notice Authorize a wallet maintainer that can interact with this\n /// reimbursement pool. Can be authorized by the owner only.\n /// @param maintainer Wallet maintainer to authorize.\n function authorizeWalletMaintainer(address maintainer) external onlyOwner {\n walletMaintainers.push(maintainer);\n isWalletMaintainer[maintainer] = walletMaintainers.length;\n\n emit WalletMaintainerAuthorized(maintainer);\n }\n\n /// @notice Authorize an SPV maintainer that can interact with this\n /// reimbursement pool. Can be authorized by the owner only.\n /// @param maintainer SPV maintainer to authorize.\n function authorizeSpvMaintainer(address maintainer) external onlyOwner {\n spvMaintainers.push(maintainer);\n isSpvMaintainer[maintainer] = spvMaintainers.length;\n\n emit SpvMaintainerAuthorized(maintainer);\n }\n\n /// @notice Unauthorize a wallet maintainer that was previously authorized to\n /// interact with the Maintainer Proxy contract. Can be unauthorized\n /// by the owner only.\n /// @dev The last maintainer is swapped with the one to be unauthorized.\n /// The unauthorized maintainer is then removed from the list. An index\n /// of the last maintainer is changed with the removed maintainer.\n /// Ex.\n /// 'walletMaintainers' list: [0x1, 0x2, 0x3, 0x4, 0x5]\n /// 'isWalletMaintainer' map: [0x1 -> 1, 0x2 -> 2, 0x3 -> 3, 0x4 -> 4, 0x5 -> 5]\n /// unauthorize: 0x3\n /// new 'walletMaintainers' list: [0x1, 0x2, 0x5, 0x4]\n /// new 'isWalletMaintainer' map: [0x1 -> 1, 0x2 -> 2, 0x4 -> 4, 0x5 -> 3]\n /// @param maintainerToUnauthorize Maintainer to unauthorize.\n function unauthorizeWalletMaintainer(address maintainerToUnauthorize)\n external\n onlyOwner\n {\n uint256 maintainerIdToUnauthorize = isWalletMaintainer[\n maintainerToUnauthorize\n ];\n\n require(maintainerIdToUnauthorize != 0, \"No maintainer to unauthorize\");\n\n address lastMaintainerAddress = walletMaintainers[\n walletMaintainers.length - 1\n ];\n\n walletMaintainers[\n maintainerIdToUnauthorize - 1\n ] = lastMaintainerAddress;\n walletMaintainers.pop();\n\n isWalletMaintainer[lastMaintainerAddress] = maintainerIdToUnauthorize;\n\n delete isWalletMaintainer[maintainerToUnauthorize];\n\n emit WalletMaintainerUnauthorized(maintainerToUnauthorize);\n }\n\n /// @notice Unauthorize an SPV maintainer that was previously authorized to\n /// interact with the Maintainer Proxy contract. Can be unauthorized\n /// by the owner only.\n /// @dev The last maintainer is swapped with the one to be unauthorized.\n /// The unauthorized maintainer is then removed from the list. An index\n /// of the last maintainer is changed with the removed maintainer.\n /// Ex.\n /// 'spvMaintainers' list: [0x1, 0x2, 0x3, 0x4, 0x5]\n /// 'isSpvMaintainer' map: [0x1 -> 1, 0x2 -> 2, 0x3 -> 3, 0x4 -> 4, 0x5 -> 5]\n /// unauthorize: 0x3\n /// new 'spvMaintainers' list: [0x1, 0x2, 0x5, 0x4]\n /// new 'isSpvMaintainer' map: [0x1 -> 1, 0x2 -> 2, 0x4 -> 4, 0x5 -> 3]\n /// @param maintainerToUnauthorize Maintainer to unauthorize.\n function unauthorizeSpvMaintainer(address maintainerToUnauthorize)\n external\n onlyOwner\n {\n uint256 maintainerIdToUnauthorize = isSpvMaintainer[\n maintainerToUnauthorize\n ];\n\n require(maintainerIdToUnauthorize != 0, \"No maintainer to unauthorize\");\n\n address lastMaintainerAddress = spvMaintainers[\n spvMaintainers.length - 1\n ];\n\n spvMaintainers[maintainerIdToUnauthorize - 1] = lastMaintainerAddress;\n spvMaintainers.pop();\n\n isSpvMaintainer[lastMaintainerAddress] = maintainerIdToUnauthorize;\n\n delete isSpvMaintainer[maintainerToUnauthorize];\n\n emit SpvMaintainerUnauthorized(maintainerToUnauthorize);\n }\n\n /// @notice Allows the Governance to upgrade the Bridge address.\n /// @dev The function does not implement any governance delay and does not\n /// check the status of the Bridge. The Governance implementation needs\n /// to ensure all requirements for the upgrade are satisfied before\n /// executing this function.\n function updateBridge(Bridge _bridge) external onlyOwner {\n bridge = _bridge;\n\n emit BridgeUpdated(address(_bridge));\n }\n\n /// @notice Updates the values of gas offset parameters.\n /// @dev Can be called only by the contract owner. The caller is responsible\n /// for validating parameters.\n /// @param newSubmitDepositSweepProofGasOffset New submit deposit sweep\n /// proof gas offset.\n /// @param newSubmitRedemptionProofGasOffset New submit redemption proof gas\n /// offset.\n /// @param newResetMovingFundsTimeoutGasOffset New reset moving funds\n /// timeout gas offset.\n /// @param newSubmitMovingFundsProofGasOffset New submit moving funds proof\n /// gas offset.\n /// @param newNotifyMovingFundsBelowDustGasOffset New notify moving funds\n /// below dust gas offset.\n /// @param newSubmitMovedFundsSweepProofGasOffset New submit moved funds\n /// sweep proof gas offset.\n /// @param newRequestNewWalletGasOffset New request new wallet gas offset.\n /// @param newNotifyWalletCloseableGasOffset New notify closeable wallet gas\n /// offset.\n /// @param newNotifyWalletClosingPeriodElapsedGasOffset New notify wallet\n /// closing period elapsed gas offset.\n /// @param newDefeatFraudChallengeGasOffset New defeat fraud challenge gas\n /// offset.\n /// @param newDefeatFraudChallengeWithHeartbeatGasOffset New defeat fraud\n /// challenge with heartbeat gas offset.\n function updateGasOffsetParameters(\n uint256 newSubmitDepositSweepProofGasOffset,\n uint256 newSubmitRedemptionProofGasOffset,\n uint256 newResetMovingFundsTimeoutGasOffset,\n uint256 newSubmitMovingFundsProofGasOffset,\n uint256 newNotifyMovingFundsBelowDustGasOffset,\n uint256 newSubmitMovedFundsSweepProofGasOffset,\n uint256 newRequestNewWalletGasOffset,\n uint256 newNotifyWalletCloseableGasOffset,\n uint256 newNotifyWalletClosingPeriodElapsedGasOffset,\n uint256 newDefeatFraudChallengeGasOffset,\n uint256 newDefeatFraudChallengeWithHeartbeatGasOffset\n ) external onlyOwner {\n submitDepositSweepProofGasOffset = newSubmitDepositSweepProofGasOffset;\n submitRedemptionProofGasOffset = newSubmitRedemptionProofGasOffset;\n resetMovingFundsTimeoutGasOffset = newResetMovingFundsTimeoutGasOffset;\n submitMovingFundsProofGasOffset = newSubmitMovingFundsProofGasOffset;\n notifyMovingFundsBelowDustGasOffset = newNotifyMovingFundsBelowDustGasOffset;\n submitMovedFundsSweepProofGasOffset = newSubmitMovedFundsSweepProofGasOffset;\n requestNewWalletGasOffset = newRequestNewWalletGasOffset;\n notifyWalletCloseableGasOffset = newNotifyWalletCloseableGasOffset;\n notifyWalletClosingPeriodElapsedGasOffset = newNotifyWalletClosingPeriodElapsedGasOffset;\n defeatFraudChallengeGasOffset = newDefeatFraudChallengeGasOffset;\n defeatFraudChallengeWithHeartbeatGasOffset = newDefeatFraudChallengeWithHeartbeatGasOffset;\n\n emit GasOffsetParametersUpdated(\n submitDepositSweepProofGasOffset,\n submitRedemptionProofGasOffset,\n resetMovingFundsTimeoutGasOffset,\n submitMovingFundsProofGasOffset,\n notifyMovingFundsBelowDustGasOffset,\n submitMovedFundsSweepProofGasOffset,\n requestNewWalletGasOffset,\n notifyWalletCloseableGasOffset,\n notifyWalletClosingPeriodElapsedGasOffset,\n defeatFraudChallengeGasOffset,\n defeatFraudChallengeWithHeartbeatGasOffset\n );\n }\n\n /// @notice Gets an entire array of wallet maintainer addresses.\n function allWalletMaintainers() external view returns (address[] memory) {\n return walletMaintainers;\n }\n\n /// @notice Gets an entire array of SPV maintainer addresses.\n function allSpvMaintainers() external view returns (address[] memory) {\n return spvMaintainers;\n }\n}\n"
@@ -346,6 +346,9 @@
346
346
  "contracts/test/ReceiveApprovalStub.sol": {
347
347
  "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.17;\n\nimport \"../token/TBTC.sol\";\n\ncontract ReceiveApprovalStub is IReceiveApproval {\n bool public shouldRevert;\n\n event ApprovalReceived(\n address from,\n uint256 value,\n address token,\n bytes extraData\n );\n\n function receiveApproval(\n address from,\n uint256 value,\n address token,\n bytes calldata extraData\n ) external override {\n if (shouldRevert) {\n revert(\"i am your father luke\");\n }\n\n emit ApprovalReceived(from, value, token, extraData);\n }\n\n function setShouldRevert(bool _shouldRevert) external {\n shouldRevert = _shouldRevert;\n }\n}\n"
348
348
  },
349
+ "contracts/test/SepoliaLightRelay.sol": {
350
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\n\n// ██████████████ ▐████▌ ██████████████\n// ██████████████ ▐████▌ ██████████████\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ██████████████ ▐████▌ ██████████████\n// ██████████████ ▐████▌ ██████████████\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n// ▐████▌ ▐████▌\n\npragma solidity 0.8.17;\n\nimport {BTCUtils} from \"@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol\";\n\nimport \"../relay/LightRelay.sol\";\n\n/// @title Sepolia Light Relay\n/// @notice SepoliaLightRelay is a stub version of LightRelay intended to be\n/// used on the Sepolia test network. It allows to set the relay's\n/// difficulty based on arbitrary Bitcoin headers thus effectively\n/// bypass the validation of difficulties of Bitcoin testnet blocks.\n/// Since difficulty in Bitcoin testnet often falls to `1` it would not\n/// be possible to validate blocks with the real LightRelay.\n/// @dev Notice that SepoliaLightRelay is derived from LightRelay so that the two\n/// contracts have the same API and correct bindings can be generated.\ncontract SepoliaLightRelay is LightRelay {\n using BTCUtils for bytes;\n using BTCUtils for uint256;\n\n /// @notice Sets the current and previous difficulty based on the difficulty\n /// inferred from the provided Bitcoin headers.\n function setDifficultyFromHeaders(bytes memory bitcoinHeaders)\n external\n onlyOwner\n {\n uint256 firstHeaderDiff = bitcoinHeaders\n .extractTarget()\n .calculateDifficulty();\n\n currentEpochDifficulty = firstHeaderDiff;\n prevEpochDifficulty = firstHeaderDiff;\n }\n}\n"
351
+ },
349
352
  "contracts/test/SystemTestRelay.sol": {
350
353
  "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.17;\n\nimport {BTCUtils} from \"@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol\";\n\nimport \"../bridge/Bridge.sol\";\n\n/// @notice Used only for system tests.\ncontract SystemTestRelay is IRelay {\n using BTCUtils for bytes;\n using BTCUtils for uint256;\n\n uint256 private currentEpochDifficulty;\n uint256 private prevEpochDifficulty;\n\n function setCurrentEpochDifficulty(uint256 _difficulty) external {\n currentEpochDifficulty = _difficulty;\n }\n\n function setPrevEpochDifficulty(uint256 _difficulty) external {\n prevEpochDifficulty = _difficulty;\n }\n\n function setCurrentEpochDifficultyFromHeaders(bytes memory bitcoinHeaders)\n external\n {\n uint256 firstHeaderDiff = bitcoinHeaders\n .extractTarget()\n .calculateDifficulty();\n\n currentEpochDifficulty = firstHeaderDiff;\n }\n\n function setPrevEpochDifficultyFromHeaders(bytes memory bitcoinHeaders)\n external\n {\n uint256 firstHeaderDiff = bitcoinHeaders\n .extractTarget()\n .calculateDifficulty();\n\n prevEpochDifficulty = firstHeaderDiff;\n }\n\n function getCurrentEpochDifficulty()\n external\n view\n override\n returns (uint256)\n {\n return currentEpochDifficulty;\n }\n\n function getPrevEpochDifficulty() external view override returns (uint256) {\n return prevEpochDifficulty;\n }\n}\n"
351
354
  },
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -174,19 +174,6 @@
174
174
  "stateMutability": "view",
175
175
  "type": "function"
176
176
  },
177
- {
178
- "inputs": [
179
- {
180
- "internalType": "uint256",
181
- "name": "amount",
182
- "type": "uint256"
183
- }
184
- ],
185
- "name": "depositWormholeTbtc",
186
- "outputs": [],
187
- "stateMutability": "nonpayable",
188
- "type": "function"
189
- },
190
177
  {
191
178
  "inputs": [
192
179
  {
@@ -423,8 +410,8 @@
423
410
  "type": "function"
424
411
  }
425
412
  ],
426
- "bytecode": "0x608060405234801561001057600080fd5b50611e6d806100206000396000f3fe60806040526004361061010e5760003560e01c80638da5cb5b116100a5578063e1308b3311610074578063f2fde38b11610059578063f2fde38b146102f1578063f4734b0c14610311578063f69785f31461033157600080fd5b8063e1308b33146102b1578063e78cea92146102d157600080fd5b80638da5cb5b1461021f578063b4ccd8681461023d578063c0c53b8b1461026a578063ca05f9851461028a57600080fd5b806349072f12116100e157806349072f12146101b45780635d21a596146101ca578063715018a6146101ea57806375b1beaa146101ff57600080fd5b80630b575fe6146101135780632d3802421461014e578063363da98e1461017257806344949c9214610194575b600080fd5b34801561011f57600080fd5b5061013161012e36600461188a565b90565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561015a57600080fd5b50610164609c5481565b604051908152602001610145565b34801561017e57600080fd5b5061019261018d36600461188a565b61035d565b005b3480156101a057600080fd5b506101926101af36600461188a565b6103a0565b3480156101c057600080fd5b50610164609b5481565b3480156101d657600080fd5b506101926101e53660046118a3565b6104d3565b3480156101f657600080fd5b506101926108a0565b34801561020b57600080fd5b5061019261021a366004611925565b6108b4565b34801561022b57600080fd5b506033546001600160a01b0316610131565b34801561024957600080fd5b50610164610258366004611951565b609a6020526000908152604090205481565b34801561027657600080fd5b5061019261028536600461198a565b61090f565b34801561029657600080fd5b506101646102a53660046119d5565b6001600160a01b031690565b3480156102bd57600080fd5b50609954610131906001600160a01b031681565b3480156102dd57600080fd5b50609754610131906001600160a01b031681565b3480156102fd57600080fd5b5061019261030c3660046119d5565b610bca565b34801561031d57600080fd5b50609854610131906001600160a01b031681565b61034461033f3660046119f2565b610c5a565b60405167ffffffffffffffff9091168152602001610145565b6103656110ab565b609b8190556040518181527f876c61ade8d7fbb62356eefa0f1cb0d6d95fc5269dbe8d0d636051daa88d73999060200160405180910390a150565b609b5481609c546103b19190611a67565b11156104045760405162461bcd60e51b815260206004820152601660248201527f4d696e74696e67206c696d69742065786365656465640000000000000000000060448201526064015b60405180910390fd5b60408051338152602081018390527ff7f6725b273ddbe730c152e645cb3a946dd37dbc34344ba45f20975ff85aeb92910160405180910390a180609c600082825461044f9190611a67565b909155505060985461046c906001600160a01b0316333084611105565b6099546040516340c10f1960e01b8152336004820152602481018390526001600160a01b03909116906340c10f1990604401600060405180830381600087803b1580156104b857600080fd5b505af11580156104cc573d6000803e3d6000fd5b5050505050565b6098546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561051c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105409190611a7a565b6097546040517fc3f511c10000000000000000000000000000000000000000000000000000000081529192506000916001600160a01b039091169063c3f511c1906105919087908790600401611a93565b6000604051808303816000875af11580156105b0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105d89190810190611bae565b6098546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610626573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a9190611a7a565b905060006106588483611be3565b9050600081116106aa5760405162461bcd60e51b815260206004820152601360248201527f4e6f2074425443207472616e736665727265640000000000000000000000000060448201526064016103fb565b6097546040517fea63738d00000000000000000000000000000000000000000000000000000000815260009161074c916001600160a01b039091169063ea63738d906106fa908890600401611c22565b600060405180830381865afa158015610717573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261073f9190810190611c56565b60e0015161012e90611d1f565b90506001600160a01b0381166107a45760405162461bcd60e51b815260206004820152601860248201527f307830207265636569766572206e6f7420616c6c6f776564000000000000000060448201526064016103fb565b609b5482609c546107b59190611a67565b11156107d7576098546107d2906001600160a01b031682846111b6565b610855565b81609c60008282546107e99190611a67565b90915550506099546040516340c10f1960e01b81526001600160a01b03838116600483015260248201859052909116906340c10f1990604401600060405180830381600087803b15801561083c57600080fd5b505af1158015610850573d6000803e3d6000fd5b505050505b604080516001600160a01b0383168152602081018490527fc7f080a0d33152d54d5972f0bac2d7984089c4849e2af42bca1a572728d339d7910160405180910390a150505050505050565b6108a86110ab565b6108b26000611204565b565b6108bc6110ab565b61ffff82166000818152609a6020908152604091829020849055815192835282018390527f1b29e2aa7a790fb04e7d6d73bf7ca63e2b4b1ffe0354fe94b4739c91f1a15359910160405180910390a15050565b600054610100900460ff161580801561092f5750600054600160ff909116105b806109495750303b158015610949575060005460ff166001145b6109bb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016103fb565b6000805460ff1916600117905580156109de576000805461ff0019166101001790555b6109e6611263565b6109ee6112d6565b6001600160a01b038416610a6a5760405162461bcd60e51b815260206004820152602760248201527f576f726d686f6c65206272696467652061646472657373206d757374206e6f7460448201527f206265203078300000000000000000000000000000000000000000000000000060648201526084016103fb565b6001600160a01b038316610acc5760405162461bcd60e51b8152602060048201526024808201527f42726964676520746f6b656e2061646472657373206d757374206e6f742062656044820152630203078360e41b60648201526084016103fb565b6001600160a01b038216610b2e5760405162461bcd60e51b8152602060048201526024808201527f4c325442544320746f6b656e2061646472657373206d757374206e6f742062656044820152630203078360e41b60648201526084016103fb565b609780546001600160a01b0380871673ffffffffffffffffffffffffffffffffffffffff1992831617909255609880548684169083161790556099805492851692909116919091179055600019609b558015610bc4576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610bd26110ab565b6001600160a01b038116610c4e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103fb565b610c5781611204565b50565b6000610c64611349565b83610cb15760405162461bcd60e51b815260206004820152601960248201527f30783020726563697069656e74206e6f7420616c6c6f7765640000000000000060448201526064016103fb565b85600003610d015760405162461bcd60e51b815260206004820152601460248201527f416d6f756e74206d757374206e6f74206265203000000000000000000000000060448201526064016103fb565b610d0a866113a2565b955085600003610d5c5760405162461bcd60e51b815260206004820152601860248201527f416d6f756e7420746f6f206c6f7720746f20627269646765000000000000000060448201526064016103fb565b6098546040516370a0823160e01b815230600482015287916001600160a01b0316906370a0823190602401602060405180830381865afa158015610da4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc89190611a7a565b1015610e3c5760405162461bcd60e51b815260206004820152603160248201527f4e6f7420656e6f75676820776f726d686f6c65207442544320696e207468652060448201527f6761746577617920746f2062726964676500000000000000000000000000000060648201526084016103fb565b61ffff85166000818152609a60209081526040918290205482518a815291820193909352908101829052606081018690526080810185905263ffffffff841660a08201527ffcdb8efef11d13bb0ebc515477ece314fdac305aeba3d6d9d371838bbe2435cf9060c00160405180910390a186609c6000828254610ebf9190611be3565b90915550506099546040517f79cc6790000000000000000000000000000000000000000000000000000000008152336004820152602481018990526001600160a01b03909116906379cc679090604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b5050609754609854610f5e93506001600160a01b03908116925016896113ca565b80611024576097546098546040517f0f5287b00000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152602481018a905261ffff89166044820152606481018890526084810187905263ffffffff861660a4820152911690630f5287b090349060c4015b60206040518083038185885af1158015610ff7573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061101c9190611d46565b915050611098565b6097546098546040805160208082018a905282518083039091018152818301928390527fc5a5ebda000000000000000000000000000000000000000000000000000000009092526001600160a01b039384169363c5a5ebda933493610fd99392909116918d918d9189918c91604401611d70565b6110a26001606555565b95945050505050565b6033546001600160a01b031633146108b25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103fb565b6040516001600160a01b0380851660248301528316604482015260648101829052610bc49085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261151f565b6040516001600160a01b0383166024820152604481018290526111ff9084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611152565b505050565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166112ce5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016103fb565b6108b2611604565b600054610100900460ff166113415760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016103fb565b6108b2611678565b60026065540361139b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103fb565b6002606555565b60006113b36402540be40083611dc0565b91506113c46402540be40083611de2565b92915050565b80158061145d57506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611437573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145b9190611a7a565b155b6114cf5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016103fb565b6040516001600160a01b0383166024820152604481018290526111ff9084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611152565b6001606555565b6000611574826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166116e39092919063ffffffff16565b8051909150156111ff57808060200190518101906115929190611df9565b6111ff5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103fb565b600054610100900460ff1661166f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016103fb565b6108b233611204565b600054610100900460ff166115185760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016103fb565b60606116f284846000856116fa565b949350505050565b6060824710156117725760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103fb565b600080866001600160a01b0316858760405161178e9190611e1b565b60006040518083038185875af1925050503d80600081146117cb576040519150601f19603f3d011682016040523d82523d6000602084013e6117d0565b606091505b50915091506117e1878383876117ec565b979650505050505050565b6060831561185b578251600003611854576001600160a01b0385163b6118545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103fb565b50816116f2565b6116f283838151156118705781518083602001fd5b8060405162461bcd60e51b81526004016103fb9190611c22565b60006020828403121561189c57600080fd5b5035919050565b600080602083850312156118b657600080fd5b823567ffffffffffffffff808211156118ce57600080fd5b818501915085601f8301126118e257600080fd5b8135818111156118f157600080fd5b86602082850101111561190357600080fd5b60209290920196919550909350505050565b61ffff81168114610c5757600080fd5b6000806040838503121561193857600080fd5b823561194381611915565b946020939093013593505050565b60006020828403121561196357600080fd5b813561196e81611915565b9392505050565b6001600160a01b0381168114610c5757600080fd5b60008060006060848603121561199f57600080fd5b83356119aa81611975565b925060208401356119ba81611975565b915060408401356119ca81611975565b809150509250925092565b6000602082840312156119e757600080fd5b813561196e81611975565b600080600080600060a08688031215611a0a57600080fd5b853594506020860135611a1c81611915565b93506040860135925060608601359150608086013563ffffffff81168114611a4357600080fd5b809150509295509295909350565b634e487b7160e01b600052601160045260246000fd5b808201808211156113c4576113c4611a51565b600060208284031215611a8c57600080fd5b5051919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715611afc57611afc611ac2565b60405290565b60005b83811015611b1d578181015183820152602001611b05565b50506000910152565b600082601f830112611b3757600080fd5b815167ffffffffffffffff80821115611b5257611b52611ac2565b604051601f8301601f19908116603f01168101908282118183101715611b7a57611b7a611ac2565b81604052838152866020858801011115611b9357600080fd5b611ba4846020830160208901611b02565b9695505050505050565b600060208284031215611bc057600080fd5b815167ffffffffffffffff811115611bd757600080fd5b6116f284828501611b26565b818103818111156113c4576113c4611a51565b60008151808452611c0e816020860160208601611b02565b601f01601f19169290920160200192915050565b60208152600061196e6020830184611bf6565b805160ff81168114611c4657600080fd5b919050565b8051611c4681611915565b600060208284031215611c6857600080fd5b815167ffffffffffffffff80821115611c8057600080fd5b908301906101008286031215611c9557600080fd5b611c9d611ad8565b611ca683611c35565b81526020830151602082015260408301516040820152611cc860608401611c4b565b606082015260808301516080820152611ce360a08401611c4b565b60a082015260c083015160c082015260e083015182811115611d0457600080fd5b611d1087828601611b26565b60e08301525095945050505050565b80516020808301519190811015611d40576000198160200360031b1b821691505b50919050565b600060208284031215611d5857600080fd5b815167ffffffffffffffff8116811461196e57600080fd5b6001600160a01b038716815285602082015261ffff8516604082015283606082015263ffffffff8316608082015260c060a08201526000611db460c0830184611bf6565b98975050505050505050565b600082611ddd57634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176113c4576113c4611a51565b600060208284031215611e0b57600080fd5b8151801515811461196e57600080fd5b60008251611e2d818460208701611b02565b919091019291505056fea26469706673582212203fcf6da3edc8eecb75051e8952eff919f1a9ccbf1e1cb6683ec8af46d847e39a64736f6c63430008110033",
427
- "deployedBytecode": "0x60806040526004361061010e5760003560e01c80638da5cb5b116100a5578063e1308b3311610074578063f2fde38b11610059578063f2fde38b146102f1578063f4734b0c14610311578063f69785f31461033157600080fd5b8063e1308b33146102b1578063e78cea92146102d157600080fd5b80638da5cb5b1461021f578063b4ccd8681461023d578063c0c53b8b1461026a578063ca05f9851461028a57600080fd5b806349072f12116100e157806349072f12146101b45780635d21a596146101ca578063715018a6146101ea57806375b1beaa146101ff57600080fd5b80630b575fe6146101135780632d3802421461014e578063363da98e1461017257806344949c9214610194575b600080fd5b34801561011f57600080fd5b5061013161012e36600461188a565b90565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561015a57600080fd5b50610164609c5481565b604051908152602001610145565b34801561017e57600080fd5b5061019261018d36600461188a565b61035d565b005b3480156101a057600080fd5b506101926101af36600461188a565b6103a0565b3480156101c057600080fd5b50610164609b5481565b3480156101d657600080fd5b506101926101e53660046118a3565b6104d3565b3480156101f657600080fd5b506101926108a0565b34801561020b57600080fd5b5061019261021a366004611925565b6108b4565b34801561022b57600080fd5b506033546001600160a01b0316610131565b34801561024957600080fd5b50610164610258366004611951565b609a6020526000908152604090205481565b34801561027657600080fd5b5061019261028536600461198a565b61090f565b34801561029657600080fd5b506101646102a53660046119d5565b6001600160a01b031690565b3480156102bd57600080fd5b50609954610131906001600160a01b031681565b3480156102dd57600080fd5b50609754610131906001600160a01b031681565b3480156102fd57600080fd5b5061019261030c3660046119d5565b610bca565b34801561031d57600080fd5b50609854610131906001600160a01b031681565b61034461033f3660046119f2565b610c5a565b60405167ffffffffffffffff9091168152602001610145565b6103656110ab565b609b8190556040518181527f876c61ade8d7fbb62356eefa0f1cb0d6d95fc5269dbe8d0d636051daa88d73999060200160405180910390a150565b609b5481609c546103b19190611a67565b11156104045760405162461bcd60e51b815260206004820152601660248201527f4d696e74696e67206c696d69742065786365656465640000000000000000000060448201526064015b60405180910390fd5b60408051338152602081018390527ff7f6725b273ddbe730c152e645cb3a946dd37dbc34344ba45f20975ff85aeb92910160405180910390a180609c600082825461044f9190611a67565b909155505060985461046c906001600160a01b0316333084611105565b6099546040516340c10f1960e01b8152336004820152602481018390526001600160a01b03909116906340c10f1990604401600060405180830381600087803b1580156104b857600080fd5b505af11580156104cc573d6000803e3d6000fd5b5050505050565b6098546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561051c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105409190611a7a565b6097546040517fc3f511c10000000000000000000000000000000000000000000000000000000081529192506000916001600160a01b039091169063c3f511c1906105919087908790600401611a93565b6000604051808303816000875af11580156105b0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105d89190810190611bae565b6098546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610626573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a9190611a7a565b905060006106588483611be3565b9050600081116106aa5760405162461bcd60e51b815260206004820152601360248201527f4e6f2074425443207472616e736665727265640000000000000000000000000060448201526064016103fb565b6097546040517fea63738d00000000000000000000000000000000000000000000000000000000815260009161074c916001600160a01b039091169063ea63738d906106fa908890600401611c22565b600060405180830381865afa158015610717573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261073f9190810190611c56565b60e0015161012e90611d1f565b90506001600160a01b0381166107a45760405162461bcd60e51b815260206004820152601860248201527f307830207265636569766572206e6f7420616c6c6f776564000000000000000060448201526064016103fb565b609b5482609c546107b59190611a67565b11156107d7576098546107d2906001600160a01b031682846111b6565b610855565b81609c60008282546107e99190611a67565b90915550506099546040516340c10f1960e01b81526001600160a01b03838116600483015260248201859052909116906340c10f1990604401600060405180830381600087803b15801561083c57600080fd5b505af1158015610850573d6000803e3d6000fd5b505050505b604080516001600160a01b0383168152602081018490527fc7f080a0d33152d54d5972f0bac2d7984089c4849e2af42bca1a572728d339d7910160405180910390a150505050505050565b6108a86110ab565b6108b26000611204565b565b6108bc6110ab565b61ffff82166000818152609a6020908152604091829020849055815192835282018390527f1b29e2aa7a790fb04e7d6d73bf7ca63e2b4b1ffe0354fe94b4739c91f1a15359910160405180910390a15050565b600054610100900460ff161580801561092f5750600054600160ff909116105b806109495750303b158015610949575060005460ff166001145b6109bb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016103fb565b6000805460ff1916600117905580156109de576000805461ff0019166101001790555b6109e6611263565b6109ee6112d6565b6001600160a01b038416610a6a5760405162461bcd60e51b815260206004820152602760248201527f576f726d686f6c65206272696467652061646472657373206d757374206e6f7460448201527f206265203078300000000000000000000000000000000000000000000000000060648201526084016103fb565b6001600160a01b038316610acc5760405162461bcd60e51b8152602060048201526024808201527f42726964676520746f6b656e2061646472657373206d757374206e6f742062656044820152630203078360e41b60648201526084016103fb565b6001600160a01b038216610b2e5760405162461bcd60e51b8152602060048201526024808201527f4c325442544320746f6b656e2061646472657373206d757374206e6f742062656044820152630203078360e41b60648201526084016103fb565b609780546001600160a01b0380871673ffffffffffffffffffffffffffffffffffffffff1992831617909255609880548684169083161790556099805492851692909116919091179055600019609b558015610bc4576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610bd26110ab565b6001600160a01b038116610c4e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103fb565b610c5781611204565b50565b6000610c64611349565b83610cb15760405162461bcd60e51b815260206004820152601960248201527f30783020726563697069656e74206e6f7420616c6c6f7765640000000000000060448201526064016103fb565b85600003610d015760405162461bcd60e51b815260206004820152601460248201527f416d6f756e74206d757374206e6f74206265203000000000000000000000000060448201526064016103fb565b610d0a866113a2565b955085600003610d5c5760405162461bcd60e51b815260206004820152601860248201527f416d6f756e7420746f6f206c6f7720746f20627269646765000000000000000060448201526064016103fb565b6098546040516370a0823160e01b815230600482015287916001600160a01b0316906370a0823190602401602060405180830381865afa158015610da4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc89190611a7a565b1015610e3c5760405162461bcd60e51b815260206004820152603160248201527f4e6f7420656e6f75676820776f726d686f6c65207442544320696e207468652060448201527f6761746577617920746f2062726964676500000000000000000000000000000060648201526084016103fb565b61ffff85166000818152609a60209081526040918290205482518a815291820193909352908101829052606081018690526080810185905263ffffffff841660a08201527ffcdb8efef11d13bb0ebc515477ece314fdac305aeba3d6d9d371838bbe2435cf9060c00160405180910390a186609c6000828254610ebf9190611be3565b90915550506099546040517f79cc6790000000000000000000000000000000000000000000000000000000008152336004820152602481018990526001600160a01b03909116906379cc679090604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b5050609754609854610f5e93506001600160a01b03908116925016896113ca565b80611024576097546098546040517f0f5287b00000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152602481018a905261ffff89166044820152606481018890526084810187905263ffffffff861660a4820152911690630f5287b090349060c4015b60206040518083038185885af1158015610ff7573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061101c9190611d46565b915050611098565b6097546098546040805160208082018a905282518083039091018152818301928390527fc5a5ebda000000000000000000000000000000000000000000000000000000009092526001600160a01b039384169363c5a5ebda933493610fd99392909116918d918d9189918c91604401611d70565b6110a26001606555565b95945050505050565b6033546001600160a01b031633146108b25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103fb565b6040516001600160a01b0380851660248301528316604482015260648101829052610bc49085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261151f565b6040516001600160a01b0383166024820152604481018290526111ff9084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611152565b505050565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166112ce5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016103fb565b6108b2611604565b600054610100900460ff166113415760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016103fb565b6108b2611678565b60026065540361139b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103fb565b6002606555565b60006113b36402540be40083611dc0565b91506113c46402540be40083611de2565b92915050565b80158061145d57506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611437573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145b9190611a7a565b155b6114cf5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016103fb565b6040516001600160a01b0383166024820152604481018290526111ff9084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611152565b6001606555565b6000611574826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166116e39092919063ffffffff16565b8051909150156111ff57808060200190518101906115929190611df9565b6111ff5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103fb565b600054610100900460ff1661166f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016103fb565b6108b233611204565b600054610100900460ff166115185760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016103fb565b60606116f284846000856116fa565b949350505050565b6060824710156117725760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016103fb565b600080866001600160a01b0316858760405161178e9190611e1b565b60006040518083038185875af1925050503d80600081146117cb576040519150601f19603f3d011682016040523d82523d6000602084013e6117d0565b606091505b50915091506117e1878383876117ec565b979650505050505050565b6060831561185b578251600003611854576001600160a01b0385163b6118545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103fb565b50816116f2565b6116f283838151156118705781518083602001fd5b8060405162461bcd60e51b81526004016103fb9190611c22565b60006020828403121561189c57600080fd5b5035919050565b600080602083850312156118b657600080fd5b823567ffffffffffffffff808211156118ce57600080fd5b818501915085601f8301126118e257600080fd5b8135818111156118f157600080fd5b86602082850101111561190357600080fd5b60209290920196919550909350505050565b61ffff81168114610c5757600080fd5b6000806040838503121561193857600080fd5b823561194381611915565b946020939093013593505050565b60006020828403121561196357600080fd5b813561196e81611915565b9392505050565b6001600160a01b0381168114610c5757600080fd5b60008060006060848603121561199f57600080fd5b83356119aa81611975565b925060208401356119ba81611975565b915060408401356119ca81611975565b809150509250925092565b6000602082840312156119e757600080fd5b813561196e81611975565b600080600080600060a08688031215611a0a57600080fd5b853594506020860135611a1c81611915565b93506040860135925060608601359150608086013563ffffffff81168114611a4357600080fd5b809150509295509295909350565b634e487b7160e01b600052601160045260246000fd5b808201808211156113c4576113c4611a51565b600060208284031215611a8c57600080fd5b5051919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715611afc57611afc611ac2565b60405290565b60005b83811015611b1d578181015183820152602001611b05565b50506000910152565b600082601f830112611b3757600080fd5b815167ffffffffffffffff80821115611b5257611b52611ac2565b604051601f8301601f19908116603f01168101908282118183101715611b7a57611b7a611ac2565b81604052838152866020858801011115611b9357600080fd5b611ba4846020830160208901611b02565b9695505050505050565b600060208284031215611bc057600080fd5b815167ffffffffffffffff811115611bd757600080fd5b6116f284828501611b26565b818103818111156113c4576113c4611a51565b60008151808452611c0e816020860160208601611b02565b601f01601f19169290920160200192915050565b60208152600061196e6020830184611bf6565b805160ff81168114611c4657600080fd5b919050565b8051611c4681611915565b600060208284031215611c6857600080fd5b815167ffffffffffffffff80821115611c8057600080fd5b908301906101008286031215611c9557600080fd5b611c9d611ad8565b611ca683611c35565b81526020830151602082015260408301516040820152611cc860608401611c4b565b606082015260808301516080820152611ce360a08401611c4b565b60a082015260c083015160c082015260e083015182811115611d0457600080fd5b611d1087828601611b26565b60e08301525095945050505050565b80516020808301519190811015611d40576000198160200360031b1b821691505b50919050565b600060208284031215611d5857600080fd5b815167ffffffffffffffff8116811461196e57600080fd5b6001600160a01b038716815285602082015261ffff8516604082015283606082015263ffffffff8316608082015260c060a08201526000611db460c0830184611bf6565b98975050505050505050565b600082611ddd57634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176113c4576113c4611a51565b600060208284031215611e0b57600080fd5b8151801515811461196e57600080fd5b60008251611e2d818460208701611b02565b919091019291505056fea26469706673582212203fcf6da3edc8eecb75051e8952eff919f1a9ccbf1e1cb6683ec8af46d847e39a64736f6c63430008110033",
413
+ "bytecode": "0x608060405234801561001057600080fd5b50611cde806100206000396000f3fe6080604052600436106100f35760003560e01c8063b4ccd8681161008a578063e78cea9211610059578063e78cea9214610296578063f2fde38b146102b6578063f4734b0c146102d6578063f69785f3146102f657600080fd5b8063b4ccd86814610202578063c0c53b8b1461022f578063ca05f9851461024f578063e1308b331461027657600080fd5b80635d21a596116100c65780635d21a5961461018f578063715018a6146101af57806375b1beaa146101c45780638da5cb5b146101e457600080fd5b80630b575fe6146100f85780632d38024214610133578063363da98e1461015757806349072f1214610179575b600080fd5b34801561010457600080fd5b506101166101133660046116fb565b90565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561013f57600080fd5b50610149609c5481565b60405190815260200161012a565b34801561016357600080fd5b506101776101723660046116fb565b610322565b005b34801561018557600080fd5b50610149609b5481565b34801561019b57600080fd5b506101776101aa366004611714565b610365565b3480156101bb57600080fd5b50610177610762565b3480156101d057600080fd5b506101776101df366004611796565b610776565b3480156101f057600080fd5b506033546001600160a01b0316610116565b34801561020e57600080fd5b5061014961021d3660046117c2565b609a6020526000908152604090205481565b34801561023b57600080fd5b5061017761024a3660046117fb565b6107d1565b34801561025b57600080fd5b5061014961026a366004611846565b6001600160a01b031690565b34801561028257600080fd5b50609954610116906001600160a01b031681565b3480156102a257600080fd5b50609754610116906001600160a01b031681565b3480156102c257600080fd5b506101776102d1366004611846565b610a8c565b3480156102e257600080fd5b50609854610116906001600160a01b031681565b610309610304366004611863565b610b1c565b60405167ffffffffffffffff909116815260200161012a565b61032a610f6d565b609b8190556040518181527f876c61ade8d7fbb62356eefa0f1cb0d6d95fc5269dbe8d0d636051daa88d73999060200160405180910390a150565b61036d610fc7565b6098546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156103b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103da91906118c2565b6097546040517fc3f511c10000000000000000000000000000000000000000000000000000000081529192506000916001600160a01b039091169063c3f511c19061042b90879087906004016118db565b6000604051808303816000875af115801561044a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261047291908101906119f6565b6098546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156104c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e491906118c2565b905060006104f28483611a41565b9050600081116105495760405162461bcd60e51b815260206004820152601360248201527f4e6f2074425443207472616e736665727265640000000000000000000000000060448201526064015b60405180910390fd5b6097546040517fea63738d0000000000000000000000000000000000000000000000000000000081526000916105eb916001600160a01b039091169063ea63738d90610599908890600401611a80565b600060405180830381865afa1580156105b6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105de9190810190611ab4565b60e0015161011390611b7d565b90506001600160a01b0381166106435760405162461bcd60e51b815260206004820152601860248201527f307830207265636569766572206e6f7420616c6c6f77656400000000000000006044820152606401610540565b609b5482609c546106549190611ba4565b111561067657609854610671906001600160a01b03168284611020565b61070d565b81609c60008282546106889190611ba4565b90915550506099546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03838116600483015260248201859052909116906340c10f1990604401600060405180830381600087803b1580156106f457600080fd5b505af1158015610708573d6000803e3d6000fd5b505050505b604080516001600160a01b0383168152602081018490527fc7f080a0d33152d54d5972f0bac2d7984089c4849e2af42bca1a572728d339d7910160405180910390a1505050505061075e6001606555565b5050565b61076a610f6d565b61077460006110d5565b565b61077e610f6d565b61ffff82166000818152609a6020908152604091829020849055815192835282018390527f1b29e2aa7a790fb04e7d6d73bf7ca63e2b4b1ffe0354fe94b4739c91f1a15359910160405180910390a15050565b600054610100900460ff16158080156107f15750600054600160ff909116105b8061080b5750303b15801561080b575060005460ff166001145b61087d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610540565b6000805460ff1916600117905580156108a0576000805461ff0019166101001790555b6108a8611134565b6108b06111a7565b6001600160a01b03841661092c5760405162461bcd60e51b815260206004820152602760248201527f576f726d686f6c65206272696467652061646472657373206d757374206e6f7460448201527f20626520307830000000000000000000000000000000000000000000000000006064820152608401610540565b6001600160a01b03831661098e5760405162461bcd60e51b8152602060048201526024808201527f42726964676520746f6b656e2061646472657373206d757374206e6f742062656044820152630203078360e41b6064820152608401610540565b6001600160a01b0382166109f05760405162461bcd60e51b8152602060048201526024808201527f4c325442544320746f6b656e2061646472657373206d757374206e6f742062656044820152630203078360e41b6064820152608401610540565b609780546001600160a01b0380871673ffffffffffffffffffffffffffffffffffffffff1992831617909255609880548684169083161790556099805492851692909116919091179055600019609b558015610a86576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610a94610f6d565b6001600160a01b038116610b105760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610540565b610b19816110d5565b50565b6000610b26610fc7565b83610b735760405162461bcd60e51b815260206004820152601960248201527f30783020726563697069656e74206e6f7420616c6c6f776564000000000000006044820152606401610540565b85600003610bc35760405162461bcd60e51b815260206004820152601460248201527f416d6f756e74206d757374206e6f7420626520300000000000000000000000006044820152606401610540565b610bcc8661121a565b955085600003610c1e5760405162461bcd60e51b815260206004820152601860248201527f416d6f756e7420746f6f206c6f7720746f2062726964676500000000000000006044820152606401610540565b6098546040516370a0823160e01b815230600482015287916001600160a01b0316906370a0823190602401602060405180830381865afa158015610c66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8a91906118c2565b1015610cfe5760405162461bcd60e51b815260206004820152603160248201527f4e6f7420656e6f75676820776f726d686f6c65207442544320696e207468652060448201527f6761746577617920746f206272696467650000000000000000000000000000006064820152608401610540565b61ffff85166000818152609a60209081526040918290205482518a815291820193909352908101829052606081018690526080810185905263ffffffff841660a08201527ffcdb8efef11d13bb0ebc515477ece314fdac305aeba3d6d9d371838bbe2435cf9060c00160405180910390a186609c6000828254610d819190611a41565b90915550506099546040517f79cc6790000000000000000000000000000000000000000000000000000000008152336004820152602481018990526001600160a01b03909116906379cc679090604401600060405180830381600087803b158015610deb57600080fd5b505af1158015610dff573d6000803e3d6000fd5b5050609754609854610e2093506001600160a01b0390811692501689611242565b80610ee6576097546098546040517f0f5287b00000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152602481018a905261ffff89166044820152606481018890526084810187905263ffffffff861660a4820152911690630f5287b090349060c4015b60206040518083038185885af1158015610eb9573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610ede9190611bb7565b915050610f5a565b6097546098546040805160208082018a905282518083039091018152818301928390527fc5a5ebda000000000000000000000000000000000000000000000000000000009092526001600160a01b039384169363c5a5ebda933493610e9b9392909116918d918d9189918c91604401611be1565b610f646001606555565b95945050505050565b6033546001600160a01b031633146107745760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610540565b6002606554036110195760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610540565b6002606555565b6040516001600160a01b0383166024820152604481018290526110c99084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611390565b505050565b6001606555565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff1661119f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610540565b610774611475565b600054610100900460ff166112125760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610540565b6107746114e9565b600061122b6402540be40083611c31565b915061123c6402540be40083611c53565b92915050565b8015806112d557506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156112af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112d391906118c2565b155b6113475760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610540565b6040516001600160a01b0383166024820152604481018290526110c99084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611065565b60006113e5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166115549092919063ffffffff16565b8051909150156110c957808060200190518101906114039190611c6a565b6110c95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610540565b600054610100900460ff166114e05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610540565b610774336110d5565b600054610100900460ff166110ce5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610540565b6060611563848460008561156b565b949350505050565b6060824710156115e35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610540565b600080866001600160a01b031685876040516115ff9190611c8c565b60006040518083038185875af1925050503d806000811461163c576040519150601f19603f3d011682016040523d82523d6000602084013e611641565b606091505b50915091506116528783838761165d565b979650505050505050565b606083156116cc5782516000036116c5576001600160a01b0385163b6116c55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610540565b5081611563565b61156383838151156116e15781518083602001fd5b8060405162461bcd60e51b81526004016105409190611a80565b60006020828403121561170d57600080fd5b5035919050565b6000806020838503121561172757600080fd5b823567ffffffffffffffff8082111561173f57600080fd5b818501915085601f83011261175357600080fd5b81358181111561176257600080fd5b86602082850101111561177457600080fd5b60209290920196919550909350505050565b61ffff81168114610b1957600080fd5b600080604083850312156117a957600080fd5b82356117b481611786565b946020939093013593505050565b6000602082840312156117d457600080fd5b81356117df81611786565b9392505050565b6001600160a01b0381168114610b1957600080fd5b60008060006060848603121561181057600080fd5b833561181b816117e6565b9250602084013561182b816117e6565b9150604084013561183b816117e6565b809150509250925092565b60006020828403121561185857600080fd5b81356117df816117e6565b600080600080600060a0868803121561187b57600080fd5b85359450602086013561188d81611786565b93506040860135925060608601359150608086013563ffffffff811681146118b457600080fd5b809150509295509295909350565b6000602082840312156118d457600080fd5b5051919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156119445761194461190a565b60405290565b60005b8381101561196557818101518382015260200161194d565b50506000910152565b600082601f83011261197f57600080fd5b815167ffffffffffffffff8082111561199a5761199a61190a565b604051601f8301601f19908116603f011681019082821181831017156119c2576119c261190a565b816040528381528660208588010111156119db57600080fd5b6119ec84602083016020890161194a565b9695505050505050565b600060208284031215611a0857600080fd5b815167ffffffffffffffff811115611a1f57600080fd5b6115638482850161196e565b634e487b7160e01b600052601160045260246000fd5b8181038181111561123c5761123c611a2b565b60008151808452611a6c81602086016020860161194a565b601f01601f19169290920160200192915050565b6020815260006117df6020830184611a54565b805160ff81168114611aa457600080fd5b919050565b8051611aa481611786565b600060208284031215611ac657600080fd5b815167ffffffffffffffff80821115611ade57600080fd5b908301906101008286031215611af357600080fd5b611afb611920565b611b0483611a93565b81526020830151602082015260408301516040820152611b2660608401611aa9565b606082015260808301516080820152611b4160a08401611aa9565b60a082015260c083015160c082015260e083015182811115611b6257600080fd5b611b6e8782860161196e565b60e08301525095945050505050565b80516020808301519190811015611b9e576000198160200360031b1b821691505b50919050565b8082018082111561123c5761123c611a2b565b600060208284031215611bc957600080fd5b815167ffffffffffffffff811681146117df57600080fd5b6001600160a01b038716815285602082015261ffff8516604082015283606082015263ffffffff8316608082015260c060a08201526000611c2560c0830184611a54565b98975050505050505050565b600082611c4e57634e487b7160e01b600052601260045260246000fd5b500490565b808202811582820484141761123c5761123c611a2b565b600060208284031215611c7c57600080fd5b815180151581146117df57600080fd5b60008251611c9e81846020870161194a565b919091019291505056fea2646970667358221220b291d4f116eaee9a0315797c6438d633227d2a991caa1d3985922e37d89cae9964736f6c63430008110033",
414
+ "deployedBytecode": "0x6080604052600436106100f35760003560e01c8063b4ccd8681161008a578063e78cea9211610059578063e78cea9214610296578063f2fde38b146102b6578063f4734b0c146102d6578063f69785f3146102f657600080fd5b8063b4ccd86814610202578063c0c53b8b1461022f578063ca05f9851461024f578063e1308b331461027657600080fd5b80635d21a596116100c65780635d21a5961461018f578063715018a6146101af57806375b1beaa146101c45780638da5cb5b146101e457600080fd5b80630b575fe6146100f85780632d38024214610133578063363da98e1461015757806349072f1214610179575b600080fd5b34801561010457600080fd5b506101166101133660046116fb565b90565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561013f57600080fd5b50610149609c5481565b60405190815260200161012a565b34801561016357600080fd5b506101776101723660046116fb565b610322565b005b34801561018557600080fd5b50610149609b5481565b34801561019b57600080fd5b506101776101aa366004611714565b610365565b3480156101bb57600080fd5b50610177610762565b3480156101d057600080fd5b506101776101df366004611796565b610776565b3480156101f057600080fd5b506033546001600160a01b0316610116565b34801561020e57600080fd5b5061014961021d3660046117c2565b609a6020526000908152604090205481565b34801561023b57600080fd5b5061017761024a3660046117fb565b6107d1565b34801561025b57600080fd5b5061014961026a366004611846565b6001600160a01b031690565b34801561028257600080fd5b50609954610116906001600160a01b031681565b3480156102a257600080fd5b50609754610116906001600160a01b031681565b3480156102c257600080fd5b506101776102d1366004611846565b610a8c565b3480156102e257600080fd5b50609854610116906001600160a01b031681565b610309610304366004611863565b610b1c565b60405167ffffffffffffffff909116815260200161012a565b61032a610f6d565b609b8190556040518181527f876c61ade8d7fbb62356eefa0f1cb0d6d95fc5269dbe8d0d636051daa88d73999060200160405180910390a150565b61036d610fc7565b6098546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156103b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103da91906118c2565b6097546040517fc3f511c10000000000000000000000000000000000000000000000000000000081529192506000916001600160a01b039091169063c3f511c19061042b90879087906004016118db565b6000604051808303816000875af115801561044a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261047291908101906119f6565b6098546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156104c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e491906118c2565b905060006104f28483611a41565b9050600081116105495760405162461bcd60e51b815260206004820152601360248201527f4e6f2074425443207472616e736665727265640000000000000000000000000060448201526064015b60405180910390fd5b6097546040517fea63738d0000000000000000000000000000000000000000000000000000000081526000916105eb916001600160a01b039091169063ea63738d90610599908890600401611a80565b600060405180830381865afa1580156105b6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105de9190810190611ab4565b60e0015161011390611b7d565b90506001600160a01b0381166106435760405162461bcd60e51b815260206004820152601860248201527f307830207265636569766572206e6f7420616c6c6f77656400000000000000006044820152606401610540565b609b5482609c546106549190611ba4565b111561067657609854610671906001600160a01b03168284611020565b61070d565b81609c60008282546106889190611ba4565b90915550506099546040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03838116600483015260248201859052909116906340c10f1990604401600060405180830381600087803b1580156106f457600080fd5b505af1158015610708573d6000803e3d6000fd5b505050505b604080516001600160a01b0383168152602081018490527fc7f080a0d33152d54d5972f0bac2d7984089c4849e2af42bca1a572728d339d7910160405180910390a1505050505061075e6001606555565b5050565b61076a610f6d565b61077460006110d5565b565b61077e610f6d565b61ffff82166000818152609a6020908152604091829020849055815192835282018390527f1b29e2aa7a790fb04e7d6d73bf7ca63e2b4b1ffe0354fe94b4739c91f1a15359910160405180910390a15050565b600054610100900460ff16158080156107f15750600054600160ff909116105b8061080b5750303b15801561080b575060005460ff166001145b61087d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610540565b6000805460ff1916600117905580156108a0576000805461ff0019166101001790555b6108a8611134565b6108b06111a7565b6001600160a01b03841661092c5760405162461bcd60e51b815260206004820152602760248201527f576f726d686f6c65206272696467652061646472657373206d757374206e6f7460448201527f20626520307830000000000000000000000000000000000000000000000000006064820152608401610540565b6001600160a01b03831661098e5760405162461bcd60e51b8152602060048201526024808201527f42726964676520746f6b656e2061646472657373206d757374206e6f742062656044820152630203078360e41b6064820152608401610540565b6001600160a01b0382166109f05760405162461bcd60e51b8152602060048201526024808201527f4c325442544320746f6b656e2061646472657373206d757374206e6f742062656044820152630203078360e41b6064820152608401610540565b609780546001600160a01b0380871673ffffffffffffffffffffffffffffffffffffffff1992831617909255609880548684169083161790556099805492851692909116919091179055600019609b558015610a86576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610a94610f6d565b6001600160a01b038116610b105760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610540565b610b19816110d5565b50565b6000610b26610fc7565b83610b735760405162461bcd60e51b815260206004820152601960248201527f30783020726563697069656e74206e6f7420616c6c6f776564000000000000006044820152606401610540565b85600003610bc35760405162461bcd60e51b815260206004820152601460248201527f416d6f756e74206d757374206e6f7420626520300000000000000000000000006044820152606401610540565b610bcc8661121a565b955085600003610c1e5760405162461bcd60e51b815260206004820152601860248201527f416d6f756e7420746f6f206c6f7720746f2062726964676500000000000000006044820152606401610540565b6098546040516370a0823160e01b815230600482015287916001600160a01b0316906370a0823190602401602060405180830381865afa158015610c66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8a91906118c2565b1015610cfe5760405162461bcd60e51b815260206004820152603160248201527f4e6f7420656e6f75676820776f726d686f6c65207442544320696e207468652060448201527f6761746577617920746f206272696467650000000000000000000000000000006064820152608401610540565b61ffff85166000818152609a60209081526040918290205482518a815291820193909352908101829052606081018690526080810185905263ffffffff841660a08201527ffcdb8efef11d13bb0ebc515477ece314fdac305aeba3d6d9d371838bbe2435cf9060c00160405180910390a186609c6000828254610d819190611a41565b90915550506099546040517f79cc6790000000000000000000000000000000000000000000000000000000008152336004820152602481018990526001600160a01b03909116906379cc679090604401600060405180830381600087803b158015610deb57600080fd5b505af1158015610dff573d6000803e3d6000fd5b5050609754609854610e2093506001600160a01b0390811692501689611242565b80610ee6576097546098546040517f0f5287b00000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152602481018a905261ffff89166044820152606481018890526084810187905263ffffffff861660a4820152911690630f5287b090349060c4015b60206040518083038185885af1158015610eb9573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610ede9190611bb7565b915050610f5a565b6097546098546040805160208082018a905282518083039091018152818301928390527fc5a5ebda000000000000000000000000000000000000000000000000000000009092526001600160a01b039384169363c5a5ebda933493610e9b9392909116918d918d9189918c91604401611be1565b610f646001606555565b95945050505050565b6033546001600160a01b031633146107745760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610540565b6002606554036110195760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610540565b6002606555565b6040516001600160a01b0383166024820152604481018290526110c99084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611390565b505050565b6001606555565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff1661119f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610540565b610774611475565b600054610100900460ff166112125760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610540565b6107746114e9565b600061122b6402540be40083611c31565b915061123c6402540be40083611c53565b92915050565b8015806112d557506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156112af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112d391906118c2565b155b6113475760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610540565b6040516001600160a01b0383166024820152604481018290526110c99084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611065565b60006113e5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166115549092919063ffffffff16565b8051909150156110c957808060200190518101906114039190611c6a565b6110c95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610540565b600054610100900460ff166114e05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610540565b610774336110d5565b600054610100900460ff166110ce5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610540565b6060611563848460008561156b565b949350505050565b6060824710156115e35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610540565b600080866001600160a01b031685876040516115ff9190611c8c565b60006040518083038185875af1925050503d806000811461163c576040519150601f19603f3d011682016040523d82523d6000602084013e611641565b606091505b50915091506116528783838761165d565b979650505050505050565b606083156116cc5782516000036116c5576001600160a01b0385163b6116c55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610540565b5081611563565b61156383838151156116e15781518083602001fd5b8060405162461bcd60e51b81526004016105409190611a80565b60006020828403121561170d57600080fd5b5035919050565b6000806020838503121561172757600080fd5b823567ffffffffffffffff8082111561173f57600080fd5b818501915085601f83011261175357600080fd5b81358181111561176257600080fd5b86602082850101111561177457600080fd5b60209290920196919550909350505050565b61ffff81168114610b1957600080fd5b600080604083850312156117a957600080fd5b82356117b481611786565b946020939093013593505050565b6000602082840312156117d457600080fd5b81356117df81611786565b9392505050565b6001600160a01b0381168114610b1957600080fd5b60008060006060848603121561181057600080fd5b833561181b816117e6565b9250602084013561182b816117e6565b9150604084013561183b816117e6565b809150509250925092565b60006020828403121561185857600080fd5b81356117df816117e6565b600080600080600060a0868803121561187b57600080fd5b85359450602086013561188d81611786565b93506040860135925060608601359150608086013563ffffffff811681146118b457600080fd5b809150509295509295909350565b6000602082840312156118d457600080fd5b5051919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156119445761194461190a565b60405290565b60005b8381101561196557818101518382015260200161194d565b50506000910152565b600082601f83011261197f57600080fd5b815167ffffffffffffffff8082111561199a5761199a61190a565b604051601f8301601f19908116603f011681019082821181831017156119c2576119c261190a565b816040528381528660208588010111156119db57600080fd5b6119ec84602083016020890161194a565b9695505050505050565b600060208284031215611a0857600080fd5b815167ffffffffffffffff811115611a1f57600080fd5b6115638482850161196e565b634e487b7160e01b600052601160045260246000fd5b8181038181111561123c5761123c611a2b565b60008151808452611a6c81602086016020860161194a565b601f01601f19169290920160200192915050565b6020815260006117df6020830184611a54565b805160ff81168114611aa457600080fd5b919050565b8051611aa481611786565b600060208284031215611ac657600080fd5b815167ffffffffffffffff80821115611ade57600080fd5b908301906101008286031215611af357600080fd5b611afb611920565b611b0483611a93565b81526020830151602082015260408301516040820152611b2660608401611aa9565b606082015260808301516080820152611b4160a08401611aa9565b60a082015260c083015160c082015260e083015182811115611b6257600080fd5b611b6e8782860161196e565b60e08301525095945050505050565b80516020808301519190811015611b9e576000198160200360031b1b821691505b50919050565b8082018082111561123c5761123c611a2b565b600060208284031215611bc957600080fd5b815167ffffffffffffffff811681146117df57600080fd5b6001600160a01b038716815285602082015261ffff8516604082015283606082015263ffffffff8316608082015260c060a08201526000611c2560c0830184611a54565b98975050505050505050565b600082611c4e57634e487b7160e01b600052601260045260246000fd5b500490565b808202811582820484141761123c5761123c611a2b565b600060208284031215611c7c57600080fd5b815180151581146117df57600080fd5b60008251611c9e81846020870161194a565b919091019291505056fea2646970667358221220b291d4f116eaee9a0315797c6438d633227d2a991caa1d3985922e37d89cae9964736f6c63430008110033",
428
415
  "linkReferences": {},
429
416
  "deployedLinkReferences": {}
430
417
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/ad2c4f91b13417738dc63e06bfaa5d8f.json"
3
+ "buildInfo": "../../../build-info/c4339f1d03c92248ba145e4a93c303ef.json"
4
4
  }