@keep-network/tbtc-v2 1.2.0 → 1.3.0-dev.0
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.
- package/artifacts/.chainId +1 -1
- package/artifacts/BLS.json +223 -0
- package/artifacts/Bank.json +50 -40
- package/artifacts/BeaconAuthorization.json +273 -0
- package/artifacts/BeaconDkg.json +241 -0
- package/artifacts/BeaconDkgValidator.json +501 -0
- package/artifacts/BeaconInactivity.json +151 -0
- package/artifacts/BeaconSortitionPool.json +1187 -0
- package/artifacts/Bridge.json +449 -32
- package/artifacts/BridgeGovernance.json +24 -24
- package/artifacts/BridgeGovernanceParameters.json +10 -10
- package/artifacts/Deposit.json +13 -13
- package/artifacts/DepositSweep.json +13 -13
- package/artifacts/DonationVault.json +17 -17
- package/artifacts/EcdsaDkgValidator.json +517 -0
- package/artifacts/EcdsaInactivity.json +156 -0
- package/artifacts/EcdsaSortitionPool.json +1187 -0
- package/artifacts/Fraud.json +14 -14
- package/artifacts/KeepRegistry.json +99 -0
- package/artifacts/KeepStake.json +286 -0
- package/artifacts/KeepToken.json +711 -0
- package/artifacts/KeepTokenStaking.json +483 -0
- package/artifacts/LightRelay.json +38 -38
- package/artifacts/MaintainerProxy.json +47 -47
- package/artifacts/MovingFunds.json +14 -14
- package/artifacts/NuCypherStakingEscrow.json +287 -0
- package/artifacts/NuCypherToken.json +711 -0
- package/artifacts/RandomBeacon.json +3271 -0
- package/artifacts/RandomBeaconChaosnet.json +252 -0
- package/artifacts/RandomBeaconGovernance.json +3499 -0
- package/artifacts/Redemption.json +13 -13
- package/artifacts/ReimbursementPool.json +509 -0
- package/artifacts/T.json +1148 -0
- package/artifacts/TBTC.json +37 -36
- package/artifacts/TBTCToken.json +738 -0
- package/artifacts/TBTCVault.json +47 -47
- package/artifacts/TokenStaking.json +2288 -0
- package/artifacts/TokenholderGovernor.json +1795 -0
- package/artifacts/TokenholderTimelock.json +1058 -0
- package/artifacts/VendingMachine.json +35 -34
- package/artifacts/VendingMachineKeep.json +400 -0
- package/artifacts/VendingMachineNuCypher.json +400 -0
- package/artifacts/VendingMachineV2.json +21 -21
- package/artifacts/VendingMachineV3.json +21 -21
- package/artifacts/WalletRegistry.json +1962 -0
- package/artifacts/WalletRegistryGovernance.json +2863 -0
- package/artifacts/Wallets.json +13 -13
- package/artifacts/solcInputs/{b0025f1f7efe4824592ac0c9793776c3.json → 8445e3932e9b9683df0e9fb9258d7b11.json} +9 -0
- package/artifacts/solcInputs/{fccb130292c8c7cc958ab4fa31a3e180.json → cc4433405642a987910ddb374547d19a.json} +15 -12
- package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
- package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
- package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.dbg.json +1 -1
- package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
- package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
- package/build/contracts/bridge/BridgeGovernanceParameters.sol/BridgeGovernanceParameters.dbg.json +1 -1
- package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
- package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +1 -1
- package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +1 -1
- package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +1 -1
- package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +1 -1
- package/build/contracts/bridge/Heartbeat.sol/Heartbeat.dbg.json +1 -1
- package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +1 -1
- package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +1 -1
- package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +1 -1
- package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +1 -1
- package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
- package/build/contracts/bridge/VendingMachineV2.sol/VendingMachineV2.dbg.json +1 -1
- package/build/contracts/bridge/VendingMachineV3.sol/VendingMachineV3.dbg.json +1 -1
- package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +1 -1
- package/build/contracts/l2/L2TBTC.sol/L2TBTC.dbg.json +1 -1
- package/build/contracts/l2/L2WormholeGateway.sol/IWormholeTokenBridge.dbg.json +1 -1
- package/build/contracts/l2/L2WormholeGateway.sol/L2WormholeGateway.dbg.json +1 -1
- package/build/contracts/maintainer/MaintainerProxy.sol/MaintainerProxy.dbg.json +1 -1
- package/build/contracts/relay/LightRelay.sol/ILightRelay.dbg.json +1 -1
- package/build/contracts/relay/LightRelay.sol/LightRelay.dbg.json +1 -1
- package/build/contracts/relay/LightRelay.sol/RelayUtils.dbg.json +1 -1
- package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
- package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +1 -1
- package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
- package/build/contracts/vault/TBTCOptimisticMinting.sol/TBTCOptimisticMinting.dbg.json +1 -1
- package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
- package/export/artifacts/@keep-network/ecdsa/contracts/EcdsaDkgValidator.sol/EcdsaDkgValidator.json +24 -24
- package/export/artifacts/@keep-network/ecdsa/contracts/WalletRegistry.sol/WalletRegistry.json +245 -245
- package/export/artifacts/@keep-network/ecdsa/contracts/libraries/EcdsaDkg.sol/EcdsaDkg.json +2 -2
- package/export/artifacts/@keep-network/ecdsa/contracts/libraries/EcdsaInactivity.sol/EcdsaInactivity.json +23 -23
- package/export/artifacts/@keep-network/random-beacon/contracts/ReimbursementPool.sol/ReimbursementPool.json +53 -53
- package/export/artifacts/@keep-network/sortition-pools/contracts/Chaosnet.sol/Chaosnet.json +21 -21
- package/export/artifacts/@keep-network/sortition-pools/contracts/Rewards.sol/Rewards.json +16 -16
- package/export/artifacts/@keep-network/sortition-pools/contracts/SortitionPool.sol/SortitionPool.json +206 -206
- package/export/artifacts/@keep-network/sortition-pools/contracts/SortitionTree.sol/SortitionTree.json +26 -26
- package/export/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.json +46 -46
- package/export/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json +36 -36
- package/export/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json +78 -78
- package/export/artifacts/@openzeppelin/contracts/token/ERC721/ERC721.sol/ERC721.json +68 -68
- package/export/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.json +43 -43
- package/export/artifacts/@thesis/solidity-contracts/contracts/token/ERC20WithPermit.sol/ERC20WithPermit.json +79 -79
- package/export/artifacts/@thesis/solidity-contracts/contracts/token/MisfundRecovery.sol/MisfundRecovery.json +42 -42
- package/export/artifacts/contracts/bank/Bank.sol/Bank.json +77 -77
- package/export/artifacts/contracts/bridge/Bridge.sol/Bridge.json +320 -320
- package/export/artifacts/contracts/bridge/VendingMachine.sol/VendingMachine.json +108 -108
- package/export/artifacts/contracts/bridge/VendingMachineV2.sol/VendingMachineV2.json +63 -63
- package/export/artifacts/contracts/bridge/VendingMachineV3.sol/VendingMachineV3.json +65 -65
- package/export/artifacts/contracts/l2/L2TBTC.sol/L2TBTC.json +194 -194
- package/export/artifacts/contracts/l2/L2WormholeGateway.sol/L2WormholeGateway.json +100 -100
- package/export/artifacts/contracts/maintainer/MaintainerProxy.sol/MaintainerProxy.json +149 -149
- package/export/artifacts/contracts/relay/LightRelay.sol/LightRelay.json +76 -76
- package/export/artifacts/contracts/test/BankStub.sol/BankStub.json +11975 -0
- package/export/artifacts/contracts/test/BridgeStub.sol/BridgeStub.json +51806 -0
- package/export/artifacts/contracts/test/GoerliLightRelay.sol/GoerliLightRelay.json +11988 -0
- package/export/artifacts/contracts/test/HeartbeatStub.sol/HeartbeatStub.json +822 -0
- package/export/artifacts/contracts/test/LightRelayStub.sol/LightRelayStub.json +12729 -0
- package/export/artifacts/contracts/test/ReceiveApprovalStub.sol/ReceiveApprovalStub.json +2160 -0
- package/export/artifacts/contracts/test/SystemTestRelay.sol/SystemTestRelay.json +3407 -0
- package/export/artifacts/contracts/test/TestERC20.sol/TestERC20.json +14263 -0
- package/export/artifacts/contracts/test/TestERC721.sol/TestERC721.json +10644 -0
- package/export/artifacts/contracts/test/TestEcdsaLib.sol/TestEcdsaLib.json +1160 -0
- package/export/artifacts/contracts/test/WormholeBridgeStub.sol/WormholeBridgeStub.json +8665 -0
- package/export/artifacts/contracts/token/TBTC.sol/TBTC.json +104 -104
- package/export/artifacts/contracts/vault/DonationVault.sol/DonationVault.json +19 -19
- package/export/artifacts/contracts/vault/TBTCVault.sol/TBTCVault.json +184 -184
- package/export/test/integration/data/bls.js +12 -0
- package/export/test/integration/data/integration.js +133 -0
- package/export/test/integration/utils/ecdsa-wallet-registry.js +370 -0
- package/export/test/integration/utils/random-beacon.js +193 -0
- package/export/{deploy/08_deploy_maintainer_proxy.js → test/integration/utils/staking.js} +35 -32
- package/export/typechain/factories/WalletRegistry__factory.js +1 -1
- package/package.json +5 -5
- package/artifacts/solcInputs/7cc3eda3cb3ff2522d18b5e7b31ea228.json +0 -102
- package/artifacts/solcInputs/802132f7da69a8a4226cb9424480847b.json +0 -218
- package/artifacts/solcInputs/887fad6b16575ba42183543c324eeb0e.json +0 -335
- package/export/deploy/00_resolve_relay.js +0 -83
- package/export/deploy/01_deploy_tbtc_v2_token.js +0 -70
- package/export/deploy/02_deploy_vending_machine.js +0 -84
- package/export/deploy/03_transfer_vending_machine_roles.js +0 -69
- package/export/deploy/04_deploy_bank.js +0 -73
- package/export/deploy/05_deploy_bridge.js +0 -178
- package/export/deploy/06_deploy_tbtc_vault.js +0 -80
- package/export/deploy/07_deploy_bridge_governance.js +0 -87
- package/export/deploy/09_bank_update_bridge.js +0 -63
- package/export/deploy/10_authorize_spv_maintainer_in_bridge.js +0 -61
- package/export/deploy/11_transfer_bank_ownership.js +0 -60
- package/export/deploy/12_transfer_bridge_governance.js +0 -63
- package/export/deploy/13_transfer_bridge_governance_ownership.js +0 -60
- package/export/deploy/14_transfer_tbtc_vault_ownership.js +0 -60
- package/export/deploy/15_transfer_maintainer_proxy_ownership.js +0 -60
- package/export/deploy/16_initialize_wallet_owner.js +0 -63
- package/export/deploy/16_transfer_proxy_admin_ownership.js +0 -73
- package/export/deploy/17_authorize_maintainer_proxy_in_bridge.js +0 -63
- package/export/deploy/17_transfer_proxy_admin_ownership.js +0 -73
- package/export/deploy/18_authorize_maintainer_proxy_in_bridge.js +0 -63
- package/export/deploy/18_authorize_maintainer_proxy_in_reimbursement_pool.js +0 -63
- package/export/deploy/19_authorize_bridge_in_reimbursement_pool.js +0 -63
- package/export/deploy/19_authorize_maintainer_proxy_in_reimbursement_pool.js +0 -63
- package/export/deploy/20_authorize_bridge_in_reimbursement_pool.js +0 -63
- package/export/deploy/20_deploy_proxy_admin_with_deputy.js +0 -80
- package/export/deploy/21_transfer_reimbursement_pool_ownership.js +0 -60
- package/export/deploy/22_deploy_proxy_admin_with_deputy.js +0 -80
- package/export/deploy/24_transfer_maintainer_proxy_ownership.js +0 -60
- package/export/deploy/25_transfer_proxy_admin_ownership.js +0 -73
- package/export/deploy/26_authorize_maintainer_proxy_in_reimbursement_pool.js +0 -70
- package/export/deploy/27_authorize_bridge_in_reimbursement_pool.js +0 -70
- package/export/deploy/28_deploy_proxy_admin_with_deputy.js +0 -80
- package/export/typechain/RelayStub.js +0 -2
- package/export/typechain/TestRelay.js +0 -2
- package/export/typechain/factories/RelayStub__factory.js +0 -546
- package/export/typechain/factories/TestRelay__factory.js +0 -168
|
@@ -94,6 +94,9 @@
|
|
|
94
94
|
"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": {
|
|
95
95
|
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n"
|
|
96
96
|
},
|
|
97
|
+
"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": {
|
|
98
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n"
|
|
99
|
+
},
|
|
97
100
|
"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": {
|
|
98
101
|
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[45] private __gap;\n}\n"
|
|
99
102
|
},
|
|
@@ -310,6 +313,9 @@
|
|
|
310
313
|
"contracts/l2/L2TBTC.sol": {
|
|
311
314
|
"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"
|
|
312
315
|
},
|
|
316
|
+
"contracts/l2/L2WormholeGateway.sol": {
|
|
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/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 /// 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(\n bridgeToken.balanceOf(address(this)) >= amount,\n \"Not enough wormhole tBTC in the gateway to bridge\"\n );\n\n require(recipient != bytes32(0), \"0x0 recipient not allowed\");\n require(amount != 0, \"Amount must not be 0\");\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"
|
|
318
|
+
},
|
|
313
319
|
"contracts/maintainer/MaintainerProxy.sol": {
|
|
314
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/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"
|
|
315
321
|
},
|
|
@@ -346,6 +352,9 @@
|
|
|
346
352
|
"contracts/test/TestERC721.sol": {
|
|
347
353
|
"content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\n\ncontract TestERC721 is ERC721 {\n string public constant NAME = \"Test ERC721 Token\";\n string public constant SYMBOL = \"TT\";\n\n constructor() ERC721(NAME, SYMBOL) {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n}\n"
|
|
348
354
|
},
|
|
355
|
+
"contracts/test/WormholeBridgeStub.sol": {
|
|
356
|
+
"content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.17;\n\nimport \"./TestERC20.sol\";\nimport \"../l2/L2WormholeGateway.sol\";\n\n/// @dev Stub contract used in L2WormholeGateway unit tests.\n/// Stub contract is used instead of a smock because of the token transfer\n/// that needs to happen in completeTransferWithPayload function.\ncontract WormholeBridgeStub is IWormholeTokenBridge {\n TestERC20 public wormholeToken;\n\n uint256 public transferAmount;\n bytes32 public receiverAddress;\n\n // Two simple events allowing to assert Wormhole bridge functions are\n // called.\n event WormholeBridgeStub_completeTransferWithPayload(bytes encodedVm);\n event WormholeBridgeStub_transferTokens(\n address token,\n uint256 amount,\n uint16 recipientChain,\n bytes32 recipient,\n uint256 arbiterFee,\n uint32 nonce\n );\n event WormholeBridgeStub_transferTokensWithPayload(\n address token,\n uint256 amount,\n uint16 recipientChain,\n bytes32 recipient,\n uint32 nonce,\n bytes payload\n );\n\n constructor(TestERC20 _wormholeToken) {\n wormholeToken = _wormholeToken;\n }\n\n function completeTransferWithPayload(bytes memory encodedVm)\n external\n returns (bytes memory)\n {\n emit WormholeBridgeStub_completeTransferWithPayload(encodedVm);\n wormholeToken.mint(msg.sender, transferAmount);\n\n // In a real implementation, encodedVm is parsed. To avoid copy-pasting\n // Wormhole code to this contract and then encoding parmaters in unit\n // tests, we allow to set the receiver address on the stub contract and\n // we return it here. The rest of the parameters does not matter.\n IWormholeTokenBridge.TransferWithPayload memory transfer = IWormholeTokenBridge\n .TransferWithPayload(\n 1, // payloadID\n 2, // amount\n 0x3000000000000000000000000000000000000000000000000000000000000000, // tokenAddress\n 4, // tokenChain\n 0x5000000000000000000000000000000000000000000000000000000000000000, // to\n 6, // toChain\n 0x7000000000000000000000000000000000000000000000000000000000000000, // fromAddress\n abi.encode(receiverAddress) // payload\n );\n\n return abi.encode(transfer);\n }\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 emit WormholeBridgeStub_transferTokens(\n token,\n amount,\n recipientChain,\n recipient,\n arbiterFee,\n nonce\n );\n return 777;\n }\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 emit WormholeBridgeStub_transferTokensWithPayload(\n token,\n amount,\n recipientChain,\n recipient,\n nonce,\n payload\n );\n return 888;\n }\n\n function parseTransferWithPayload(bytes memory encoded)\n external\n pure\n returns (IWormholeTokenBridge.TransferWithPayload memory transfer)\n {\n return abi.decode(encoded, (IWormholeTokenBridge.TransferWithPayload));\n }\n\n function setTransferAmount(uint256 _transferAmount) external {\n transferAmount = _transferAmount;\n }\n\n function setReceiverAddress(bytes32 _receiverAddress) external {\n receiverAddress = _receiverAddress;\n }\n\n // Allows to mint Wormhole tBTC for depositWormholeTbtc unit tests.\n function mintWormholeToken(address to, uint256 amount) external {\n wormholeToken.mint(to, amount);\n }\n}\n"
|
|
357
|
+
},
|
|
349
358
|
"contracts/token/TBTC.sol": {
|
|
350
359
|
"content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.17;\n\nimport \"@thesis/solidity-contracts/contracts/token/ERC20WithPermit.sol\";\nimport \"@thesis/solidity-contracts/contracts/token/MisfundRecovery.sol\";\n\ncontract TBTC is ERC20WithPermit, MisfundRecovery {\n constructor() ERC20WithPermit(\"tBTC v2\", \"tBTC\") {}\n}\n"
|
|
351
360
|
},
|