@keep-network/tbtc-v2 1.2.0-dev.0 → 1.2.0-dev.1
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/BLS.json +1 -1
- package/artifacts/Bank.json +8 -8
- package/artifacts/BeaconAuthorization.json +1 -1
- package/artifacts/BeaconDkg.json +1 -1
- package/artifacts/BeaconDkgValidator.json +1 -1
- package/artifacts/BeaconInactivity.json +1 -1
- package/artifacts/BeaconSortitionPool.json +3 -3
- package/artifacts/Bridge.json +5 -5
- package/artifacts/BridgeGovernance.json +2 -2
- package/artifacts/BridgeGovernanceParameters.json +2 -2
- package/artifacts/Deposit.json +2 -2
- package/artifacts/DepositSweep.json +2 -2
- package/artifacts/DonationVault.json +5 -5
- package/artifacts/EcdsaDkgValidator.json +1 -1
- package/artifacts/EcdsaInactivity.json +1 -1
- package/artifacts/EcdsaSortitionPool.json +3 -3
- package/artifacts/Fraud.json +2 -2
- package/artifacts/KeepRegistry.json +1 -1
- package/artifacts/KeepStake.json +2 -2
- package/artifacts/KeepToken.json +2 -2
- package/artifacts/KeepTokenStaking.json +1 -1
- package/artifacts/LightRelay.json +19 -19
- package/artifacts/MaintainerProxy.json +22 -22
- package/artifacts/MovingFunds.json +2 -2
- package/artifacts/NuCypherStakingEscrow.json +1 -1
- package/artifacts/NuCypherToken.json +2 -2
- package/artifacts/RandomBeacon.json +2 -2
- package/artifacts/RandomBeaconChaosnet.json +2 -2
- package/artifacts/RandomBeaconGovernance.json +2 -2
- package/artifacts/Redemption.json +2 -2
- package/artifacts/ReimbursementPool.json +2 -2
- package/artifacts/T.json +2 -2
- package/artifacts/TBTC.json +10 -10
- package/artifacts/TBTCToken.json +10 -10
- package/artifacts/TBTCVault.json +24 -24
- package/artifacts/TokenStaking.json +1 -1
- package/artifacts/TokenholderGovernor.json +9 -9
- package/artifacts/TokenholderTimelock.json +8 -8
- package/artifacts/VendingMachine.json +11 -11
- package/artifacts/VendingMachineKeep.json +1 -1
- package/artifacts/VendingMachineNuCypher.json +1 -1
- package/artifacts/VendingMachineV2.json +4 -4
- package/artifacts/VendingMachineV3.json +4 -4
- package/artifacts/WalletRegistry.json +5 -5
- package/artifacts/WalletRegistryGovernance.json +2 -2
- package/artifacts/Wallets.json +2 -2
- package/artifacts/solcInputs/{b0025f1f7efe4824592ac0c9793776c3.json → 8445e3932e9b9683df0e9fb9258d7b11.json} +9 -0
- 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 +4 -0
- package/build/contracts/l2/L2WormholeGateway.sol/IWormholeTokenBridge.json +179 -0
- package/build/contracts/l2/L2WormholeGateway.sol/L2WormholeGateway.dbg.json +4 -0
- package/build/contracts/l2/L2WormholeGateway.sol/L2WormholeGateway.json +430 -0
- 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/contracts/l2/L2WormholeGateway.sol +389 -0
- package/export/artifacts/@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol/BTCUtils.json +20 -20
- package/export/artifacts/@keep-network/ecdsa/contracts/EcdsaDkgValidator.sol/EcdsaDkgValidator.json +1996 -1996
- package/export/artifacts/@keep-network/ecdsa/contracts/libraries/EcdsaDkg.sol/EcdsaDkg.json +20 -20
- package/export/artifacts/@keep-network/ecdsa/contracts/libraries/EcdsaInactivity.sol/EcdsaInactivity.json +1846 -1846
- package/export/artifacts/@keep-network/random-beacon/contracts/ReimbursementPool.sol/ReimbursementPool.json +571 -571
- package/export/artifacts/@keep-network/sortition-pools/contracts/Chaosnet.sol/Chaosnet.json +506 -506
- package/export/artifacts/@keep-network/sortition-pools/contracts/Rewards.sol/Rewards.json +23 -23
- package/export/artifacts/@keep-network/sortition-pools/contracts/SortitionPool.sol/SortitionPool.json +2481 -2481
- package/export/artifacts/@keep-network/sortition-pools/contracts/SortitionTree.sol/SortitionTree.json +465 -465
- package/export/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.json +614 -614
- package/export/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json +640 -640
- package/export/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json +1079 -1079
- package/export/artifacts/@openzeppelin/contracts/token/ERC721/ERC721.sol/ERC721.json +1945 -1945
- package/export/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.json +696 -696
- package/export/artifacts/@thesis/solidity-contracts/contracts/token/ERC20WithPermit.sol/ERC20WithPermit.json +2613 -2613
- package/export/artifacts/@thesis/solidity-contracts/contracts/token/MisfundRecovery.sol/MisfundRecovery.json +779 -779
- package/export/artifacts/contracts/bank/Bank.sol/Bank.json +1949 -1949
- package/export/artifacts/contracts/bridge/Bridge.sol/Bridge.json +7365 -7365
- package/export/artifacts/contracts/bridge/VendingMachine.sol/VendingMachine.json +1359 -1359
- package/export/artifacts/contracts/bridge/VendingMachineV2.sol/VendingMachineV2.json +1029 -1029
- package/export/artifacts/contracts/bridge/VendingMachineV3.sol/VendingMachineV3.json +1181 -1181
- package/export/artifacts/contracts/l2/L2TBTC.sol/L2TBTC.json +3122 -3122
- package/export/artifacts/contracts/l2/L2WormholeGateway.sol/L2WormholeGateway.json +15104 -0
- package/export/artifacts/contracts/maintainer/MaintainerProxy.sol/MaintainerProxy.json +2442 -2442
- package/export/artifacts/contracts/relay/LightRelay.sol/LightRelay.json +1941 -1941
- package/export/artifacts/contracts/test/BankStub.sol/BankStub.json +1951 -1951
- package/export/artifacts/contracts/test/BridgeStub.sol/BridgeStub.json +8406 -8406
- package/export/artifacts/contracts/test/GoerliLightRelay.sol/GoerliLightRelay.json +1941 -1941
- package/export/artifacts/contracts/test/HeartbeatStub.sol/HeartbeatStub.json +132 -132
- package/export/artifacts/contracts/test/LightRelayStub.sol/LightRelayStub.json +2066 -2066
- package/export/artifacts/contracts/test/ReceiveApprovalStub.sol/ReceiveApprovalStub.json +354 -354
- package/export/artifacts/contracts/test/SystemTestRelay.sol/SystemTestRelay.json +568 -568
- package/export/artifacts/contracts/test/TestERC20.sol/TestERC20.json +2370 -2370
- package/export/artifacts/contracts/test/TestERC721.sol/TestERC721.json +1768 -1768
- package/export/artifacts/contracts/test/TestEcdsaLib.sol/TestEcdsaLib.json +191 -191
- package/export/artifacts/contracts/test/WormholeBridgeStub.sol/WormholeBridgeStub.json +8665 -0
- package/export/artifacts/contracts/token/TBTC.sol/TBTC.json +2949 -2949
- package/export/artifacts/contracts/vault/DonationVault.sol/DonationVault.json +866 -866
- package/export/artifacts/contracts/vault/TBTCVault.sol/TBTCVault.json +3525 -3525
- package/export/typechain/IWormholeTokenBridge.js +2 -0
- package/export/typechain/L2WormholeGateway.js +2 -0
- package/export/typechain/ReentrancyGuardUpgradeable.js +2 -0
- package/export/typechain/WormholeBridgeStub.js +2 -0
- package/export/typechain/factories/IWormholeTokenBridge__factory.js +190 -0
- package/export/typechain/factories/L2WormholeGateway__factory.js +509 -0
- package/export/typechain/factories/ReentrancyGuardUpgradeable__factory.js +35 -0
- package/export/typechain/factories/WormholeBridgeStub__factory.js +451 -0
- package/export/typechain/index.js +10 -2
- package/package.json +1 -1
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
|
|
3
|
+
// ██████████████ ▐████▌ ██████████████
|
|
4
|
+
// ██████████████ ▐████▌ ██████████████
|
|
5
|
+
// ▐████▌ ▐████▌
|
|
6
|
+
// ▐████▌ ▐████▌
|
|
7
|
+
// ██████████████ ▐████▌ ██████████████
|
|
8
|
+
// ██████████████ ▐████▌ ██████████████
|
|
9
|
+
// ▐████▌ ▐████▌
|
|
10
|
+
// ▐████▌ ▐████▌
|
|
11
|
+
// ▐████▌ ▐████▌
|
|
12
|
+
// ▐████▌ ▐████▌
|
|
13
|
+
// ▐████▌ ▐████▌
|
|
14
|
+
// ▐████▌ ▐████▌
|
|
15
|
+
|
|
16
|
+
pragma solidity ^0.8.17;
|
|
17
|
+
|
|
18
|
+
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
|
19
|
+
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
|
|
20
|
+
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
|
|
21
|
+
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
|
|
22
|
+
|
|
23
|
+
import "./L2TBTC.sol";
|
|
24
|
+
|
|
25
|
+
/// @title IWormholeTokenBridge
|
|
26
|
+
/// @notice Wormhole Token Bridge interface. Contains only selected functions
|
|
27
|
+
/// used by L2WormholeGateway.
|
|
28
|
+
interface IWormholeTokenBridge {
|
|
29
|
+
function completeTransferWithPayload(bytes memory encodedVm)
|
|
30
|
+
external
|
|
31
|
+
returns (bytes memory);
|
|
32
|
+
|
|
33
|
+
function parseTransferWithPayload(bytes memory encoded)
|
|
34
|
+
external
|
|
35
|
+
pure
|
|
36
|
+
returns (TransferWithPayload memory transfer);
|
|
37
|
+
|
|
38
|
+
function transferTokens(
|
|
39
|
+
address token,
|
|
40
|
+
uint256 amount,
|
|
41
|
+
uint16 recipientChain,
|
|
42
|
+
bytes32 recipient,
|
|
43
|
+
uint256 arbiterFee,
|
|
44
|
+
uint32 nonce
|
|
45
|
+
) external payable returns (uint64 sequence);
|
|
46
|
+
|
|
47
|
+
function transferTokensWithPayload(
|
|
48
|
+
address token,
|
|
49
|
+
uint256 amount,
|
|
50
|
+
uint16 recipientChain,
|
|
51
|
+
bytes32 recipient,
|
|
52
|
+
uint32 nonce,
|
|
53
|
+
bytes memory payload
|
|
54
|
+
) external payable returns (uint64 sequence);
|
|
55
|
+
|
|
56
|
+
struct TransferWithPayload {
|
|
57
|
+
uint8 payloadID;
|
|
58
|
+
uint256 amount;
|
|
59
|
+
bytes32 tokenAddress;
|
|
60
|
+
uint16 tokenChain;
|
|
61
|
+
bytes32 to;
|
|
62
|
+
uint16 toChain;
|
|
63
|
+
bytes32 fromAddress;
|
|
64
|
+
bytes payload;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// @title L2WormholeGateway
|
|
69
|
+
/// @notice Selected cross-ecosystem bridges are given the minting authority for
|
|
70
|
+
/// tBTC token on L2 and sidechains. This contract gives a minting
|
|
71
|
+
/// authority to the Wormhole Bridge.
|
|
72
|
+
///
|
|
73
|
+
/// The process of bridging from L1 to L2 (or sidechain) looks as
|
|
74
|
+
/// follows:
|
|
75
|
+
/// 1. There is a tBTC holder on L1. The holder goes to the Wormhole
|
|
76
|
+
/// Portal and selects the chain they want to bridge to.
|
|
77
|
+
/// 2. The holder submits one transaction to L1 locking their tBTC
|
|
78
|
+
/// tokens in the bridge’s smart contract. After the transaction is
|
|
79
|
+
/// mined, they wait about 15 minutes for the Ethereum block
|
|
80
|
+
/// finality.
|
|
81
|
+
/// 3. The holder submits one transaction to L2 that is minting tokens.
|
|
82
|
+
/// After that transaction is mined, they have their tBTC on L2.
|
|
83
|
+
///
|
|
84
|
+
/// The process of bridging from L2 (or sidechain) to L1 looks as
|
|
85
|
+
/// follows:
|
|
86
|
+
/// 1. There is a tBTC holder on L2. That holder goes to the Wormhole
|
|
87
|
+
/// Portal and selects one of the L2 chains they want to bridge from.
|
|
88
|
+
/// 2. The holder submits one transaction to L2 that is burning the
|
|
89
|
+
/// token. After the transaction is mined, they wait about 15 minutes
|
|
90
|
+
/// for the L2 block finality.
|
|
91
|
+
/// 3. The holder submits one transaction to L1 unlocking their tBTC
|
|
92
|
+
/// tokens from the bridge’s smart contract. After that transaction
|
|
93
|
+
/// is mined, they have their tBTC on L1.
|
|
94
|
+
///
|
|
95
|
+
/// This smart contract is integrated with step 3 of L1->L2 bridging and
|
|
96
|
+
/// step 1 of L2->L1 or L2->L2 bridging. When the user redeems token on
|
|
97
|
+
/// L2, this contract receives the Wormhole tBTC representation and
|
|
98
|
+
/// mints the canonical tBTC in an equal amount. When user sends their
|
|
99
|
+
/// token from L1, this contract burns the canonical tBTC and sends
|
|
100
|
+
/// Wormhole tBTC representation through the bridge in an equal amount.
|
|
101
|
+
/// @dev This contract is supposed to be deployed behind a transparent
|
|
102
|
+
/// upgradeable proxy.
|
|
103
|
+
contract L2WormholeGateway is
|
|
104
|
+
Initializable,
|
|
105
|
+
OwnableUpgradeable,
|
|
106
|
+
ReentrancyGuardUpgradeable
|
|
107
|
+
{
|
|
108
|
+
using SafeERC20Upgradeable for IERC20Upgradeable;
|
|
109
|
+
|
|
110
|
+
/// @notice Reference to the Wormhole Token Bridge contract.
|
|
111
|
+
IWormholeTokenBridge public bridge;
|
|
112
|
+
|
|
113
|
+
/// @notice Wormhole tBTC token representation.
|
|
114
|
+
IERC20Upgradeable public bridgeToken;
|
|
115
|
+
|
|
116
|
+
/// @notice Canonical tBTC token.
|
|
117
|
+
L2TBTC public tbtc;
|
|
118
|
+
|
|
119
|
+
/// @notice Maps Wormhole chain ID to the Wormhole tBTC gateway address on
|
|
120
|
+
/// that chain. For example, this chain's ID should be mapped to
|
|
121
|
+
/// this contract's address. If there is no Wormhole tBTC gateway
|
|
122
|
+
/// address on the given chain, there is no entry in this mapping.
|
|
123
|
+
/// The mapping holds addresses in a Wormhole-specific format, where
|
|
124
|
+
/// Ethereum address is left-padded with zeros.
|
|
125
|
+
mapping(uint16 => bytes32) public gateways;
|
|
126
|
+
|
|
127
|
+
/// @notice Minting limit for this gateway. Useful for early days of testing
|
|
128
|
+
/// the system. The gateway can not mint more canonical tBTC than
|
|
129
|
+
/// this limit.
|
|
130
|
+
uint256 public mintingLimit;
|
|
131
|
+
|
|
132
|
+
/// @notice The amount of tBTC minted by this contract. tBTC burned by this
|
|
133
|
+
/// contract decreases this amount.
|
|
134
|
+
uint256 public mintedAmount;
|
|
135
|
+
|
|
136
|
+
event WormholeTbtcReceived(address receiver, uint256 amount);
|
|
137
|
+
|
|
138
|
+
event WormholeTbtcSent(
|
|
139
|
+
uint256 amount,
|
|
140
|
+
uint16 recipientChain,
|
|
141
|
+
bytes32 gateway,
|
|
142
|
+
bytes32 recipient,
|
|
143
|
+
uint256 arbiterFee,
|
|
144
|
+
uint32 nonce
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
event WormholeTbtcDeposited(address depositor, uint256 amount);
|
|
148
|
+
|
|
149
|
+
event GatewayAddressUpdated(uint16 chainId, bytes32 gateway);
|
|
150
|
+
|
|
151
|
+
event MintingLimitUpdated(uint256 mintingLimit);
|
|
152
|
+
|
|
153
|
+
function initialize(
|
|
154
|
+
IWormholeTokenBridge _bridge,
|
|
155
|
+
IERC20Upgradeable _bridgeToken,
|
|
156
|
+
L2TBTC _tbtc
|
|
157
|
+
) external initializer {
|
|
158
|
+
__Ownable_init();
|
|
159
|
+
__ReentrancyGuard_init();
|
|
160
|
+
|
|
161
|
+
require(
|
|
162
|
+
address(_bridge) != address(0),
|
|
163
|
+
"Wormhole bridge address must not be 0x0"
|
|
164
|
+
);
|
|
165
|
+
require(
|
|
166
|
+
address(_bridgeToken) != address(0),
|
|
167
|
+
"Bridge token address must not be 0x0"
|
|
168
|
+
);
|
|
169
|
+
require(
|
|
170
|
+
address(_tbtc) != address(0),
|
|
171
|
+
"L2TBTC token address must not be 0x0"
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
bridge = _bridge;
|
|
175
|
+
bridgeToken = _bridgeToken;
|
|
176
|
+
tbtc = _tbtc;
|
|
177
|
+
mintingLimit = type(uint256).max;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/// @notice This function is called when the user sends their token from L2.
|
|
181
|
+
/// The contract burns the canonical tBTC from the user and sends
|
|
182
|
+
/// wormhole tBTC representation over the bridge.
|
|
183
|
+
/// Keep in mind that when multiple bridges receive a minting
|
|
184
|
+
/// authority on the canonical tBTC, this function may not be able
|
|
185
|
+
/// to send all amounts of tBTC through the Wormhole bridge. The
|
|
186
|
+
/// capability of Wormhole Bridge to send tBTC from the chain is
|
|
187
|
+
/// limited to the amount of tBTC bridged through Wormhole to that
|
|
188
|
+
/// chain.
|
|
189
|
+
/// @dev Requirements:
|
|
190
|
+
/// - The sender must have at least `amount` of the canonical tBTC and
|
|
191
|
+
/// it has to be approved for L2WormholeGateway.
|
|
192
|
+
/// - The L2WormholeGateway must have at least `amount` of the wormhole
|
|
193
|
+
/// tBTC.
|
|
194
|
+
/// - The recipient must not be 0x0.
|
|
195
|
+
/// - The amount to transfer must not be 0.
|
|
196
|
+
/// Depending if Wormhole tBTC gateway is registered on the target
|
|
197
|
+
/// chain, this function uses transfer or transfer with payload over
|
|
198
|
+
/// the Wormhole bridge.
|
|
199
|
+
/// @param amount The amount of tBTC to be sent.
|
|
200
|
+
/// @param recipientChain The Wormhole recipient chain ID.
|
|
201
|
+
/// @param recipient The address of the recipient in the Wormhole format.
|
|
202
|
+
/// @param arbiterFee The Wormhole arbiter fee. Ignored if sending
|
|
203
|
+
/// tBTC to chain with Wormhole tBTC gateway.
|
|
204
|
+
/// @param nonce The Wormhole nonce used to batch messages together.
|
|
205
|
+
/// @return The Wormhole sequence number.
|
|
206
|
+
function sendTbtc(
|
|
207
|
+
uint256 amount,
|
|
208
|
+
uint16 recipientChain,
|
|
209
|
+
bytes32 recipient,
|
|
210
|
+
uint256 arbiterFee,
|
|
211
|
+
uint32 nonce
|
|
212
|
+
) external payable nonReentrant returns (uint64) {
|
|
213
|
+
require(
|
|
214
|
+
bridgeToken.balanceOf(address(this)) >= amount,
|
|
215
|
+
"Not enough wormhole tBTC in the gateway to bridge"
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
require(recipient != bytes32(0), "0x0 recipient not allowed");
|
|
219
|
+
require(amount != 0, "Amount must not be 0");
|
|
220
|
+
|
|
221
|
+
bytes32 gateway = gateways[recipientChain];
|
|
222
|
+
|
|
223
|
+
emit WormholeTbtcSent(
|
|
224
|
+
amount,
|
|
225
|
+
recipientChain,
|
|
226
|
+
gateway,
|
|
227
|
+
recipient,
|
|
228
|
+
arbiterFee,
|
|
229
|
+
nonce
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
mintedAmount -= amount;
|
|
233
|
+
tbtc.burnFrom(msg.sender, amount);
|
|
234
|
+
bridgeToken.safeApprove(address(bridge), amount);
|
|
235
|
+
|
|
236
|
+
if (gateway == bytes32(0)) {
|
|
237
|
+
// No Wormhole tBTC gateway on the target chain. The token minted
|
|
238
|
+
// by Wormhole should be considered canonical.
|
|
239
|
+
return
|
|
240
|
+
bridge.transferTokens{value: msg.value}(
|
|
241
|
+
address(bridgeToken),
|
|
242
|
+
amount,
|
|
243
|
+
recipientChain,
|
|
244
|
+
recipient,
|
|
245
|
+
arbiterFee,
|
|
246
|
+
nonce
|
|
247
|
+
);
|
|
248
|
+
} else {
|
|
249
|
+
// There is a Wormhole tBTC gateway on the target chain.
|
|
250
|
+
// The gateway needs to mint canonical tBTC for the recipient
|
|
251
|
+
// encoded in the payload.
|
|
252
|
+
return
|
|
253
|
+
bridge.transferTokensWithPayload{value: msg.value}(
|
|
254
|
+
address(bridgeToken),
|
|
255
|
+
amount,
|
|
256
|
+
recipientChain,
|
|
257
|
+
gateway,
|
|
258
|
+
nonce,
|
|
259
|
+
abi.encode(recipient)
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/// @notice This function is called when the user redeems their token on L2.
|
|
265
|
+
/// The contract receives Wormhole tBTC representation and mints the
|
|
266
|
+
/// canonical tBTC for the user.
|
|
267
|
+
/// If the tBTC minting limit has been reached by this contract,
|
|
268
|
+
/// instead of minting tBTC the receiver address receives Wormhole
|
|
269
|
+
/// tBTC representation.
|
|
270
|
+
/// @dev Requirements:
|
|
271
|
+
/// - The receiver of Wormhole tBTC should be the L2WormholeGateway
|
|
272
|
+
/// contract.
|
|
273
|
+
/// - The receiver of the canonical tBTC should be abi-encoded in the
|
|
274
|
+
/// payload.
|
|
275
|
+
/// - The receiver of the canonical tBTC must not be the zero address.
|
|
276
|
+
/// The Wormhole Token Bridge contract has protection against redeeming
|
|
277
|
+
/// the same VAA again. When a Token Bridge VAA is redeemed, its
|
|
278
|
+
/// message body hash is stored in a map. This map is used to check
|
|
279
|
+
/// whether the hash has already been set in this map. For this reason,
|
|
280
|
+
/// this function does not have to be nonReentrant.
|
|
281
|
+
/// @param encodedVm A byte array containing a Wormhole VAA signed by the
|
|
282
|
+
/// guardians.
|
|
283
|
+
function receiveTbtc(bytes calldata encodedVm) external {
|
|
284
|
+
// ITokenBridge.completeTransferWithPayload completes a contract-controlled
|
|
285
|
+
// transfer of an ERC20 token. Calling this function is not enough to
|
|
286
|
+
// ensure L2WormholeGateway received Wormhole tBTC representation.
|
|
287
|
+
// Instead of going too deep into the ITokenBridge implementation,
|
|
288
|
+
// asserting who is the receiver of the token, and which token it is,
|
|
289
|
+
// we check the balance before the ITokenBridge call and the balance
|
|
290
|
+
// after ITokenBridge call. This way, we are sure this contract received
|
|
291
|
+
// Wormhole tBTC token in the given amount. This is transparent to
|
|
292
|
+
// all potential upgrades of ITokenBridge implementation and no other
|
|
293
|
+
// validations are needed.
|
|
294
|
+
uint256 balanceBefore = bridgeToken.balanceOf(address(this));
|
|
295
|
+
bytes memory encoded = bridge.completeTransferWithPayload(encodedVm);
|
|
296
|
+
uint256 balanceAfter = bridgeToken.balanceOf(address(this));
|
|
297
|
+
|
|
298
|
+
uint256 amount = balanceAfter - balanceBefore;
|
|
299
|
+
// Protect against the custody of irrelevant tokens.
|
|
300
|
+
require(amount > 0, "No tBTC transferred");
|
|
301
|
+
|
|
302
|
+
address receiver = fromWormholeAddress(
|
|
303
|
+
bytes32(bridge.parseTransferWithPayload(encoded).payload)
|
|
304
|
+
);
|
|
305
|
+
require(receiver != address(0), "0x0 receiver not allowed");
|
|
306
|
+
|
|
307
|
+
// We send wormhole tBTC OR mint canonical tBTC. We do not want to send
|
|
308
|
+
// dust. Sending wormhole tBTC is an exceptional situation and we want
|
|
309
|
+
// to keep it simple.
|
|
310
|
+
if (mintedAmount + amount > mintingLimit) {
|
|
311
|
+
bridgeToken.safeTransfer(receiver, amount);
|
|
312
|
+
} else {
|
|
313
|
+
// The function is non-reentrant given bridge.completeTransferWithPayload
|
|
314
|
+
// call that does not allow to use the same VAA again.
|
|
315
|
+
// slither-disable-next-line reentrancy-benign
|
|
316
|
+
mintedAmount += amount;
|
|
317
|
+
tbtc.mint(receiver, amount);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// The function is non-reentrant given bridge.completeTransferWithPayload
|
|
321
|
+
// call that does not allow to use the same VAA again.
|
|
322
|
+
// slither-disable-next-line reentrancy-events
|
|
323
|
+
emit WormholeTbtcReceived(receiver, amount);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/// @notice Allows to deposit Wormhole tBTC token in exchange for canonical
|
|
327
|
+
/// tBTC. Useful in a situation when user received wormhole tBTC
|
|
328
|
+
/// instead of canonical tBTC. One example of such situation is
|
|
329
|
+
/// when the minting limit was exceeded but the user minted anyway.
|
|
330
|
+
/// @dev Requirements:
|
|
331
|
+
/// - The sender must have at least `amount` of the Wormhole tBTC and
|
|
332
|
+
/// it has to be approved for L2WormholeGateway.
|
|
333
|
+
/// - The minting limit must allow for minting the given amount.
|
|
334
|
+
/// @param amount The amount of Wormhole tBTC to deposit.
|
|
335
|
+
function depositWormholeTbtc(uint256 amount) external {
|
|
336
|
+
require(
|
|
337
|
+
mintedAmount + amount <= mintingLimit,
|
|
338
|
+
"Minting limit exceeded"
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
emit WormholeTbtcDeposited(msg.sender, amount);
|
|
342
|
+
mintedAmount += amount;
|
|
343
|
+
bridgeToken.safeTransferFrom(msg.sender, address(this), amount);
|
|
344
|
+
tbtc.mint(msg.sender, amount);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/// @notice Lets the governance to update the tBTC gateway address on the
|
|
348
|
+
/// chain with the given Wormhole ID.
|
|
349
|
+
/// @dev Use toWormholeAddress function to convert between Ethereum and
|
|
350
|
+
/// Wormhole address formats.
|
|
351
|
+
/// @param chainId Wormhole ID of the chain.
|
|
352
|
+
/// @param gateway Address of tBTC gateway on the given chain in a Wormhole
|
|
353
|
+
/// format.
|
|
354
|
+
function updateGatewayAddress(uint16 chainId, bytes32 gateway)
|
|
355
|
+
external
|
|
356
|
+
onlyOwner
|
|
357
|
+
{
|
|
358
|
+
gateways[chainId] = gateway;
|
|
359
|
+
emit GatewayAddressUpdated(chainId, gateway);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/// @notice Lets the governance to update the tBTC minting limit for this
|
|
363
|
+
/// contract.
|
|
364
|
+
/// @param _mintingLimit The new minting limit.
|
|
365
|
+
function updateMintingLimit(uint256 _mintingLimit) external onlyOwner {
|
|
366
|
+
mintingLimit = _mintingLimit;
|
|
367
|
+
emit MintingLimitUpdated(_mintingLimit);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/// @notice Converts Ethereum address into Wormhole format.
|
|
371
|
+
/// @param _address The address to convert.
|
|
372
|
+
function toWormholeAddress(address _address)
|
|
373
|
+
external
|
|
374
|
+
pure
|
|
375
|
+
returns (bytes32)
|
|
376
|
+
{
|
|
377
|
+
return bytes32(uint256(uint160(_address)));
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/// @notice Converts Wormhole address into Ethereum format.
|
|
381
|
+
/// @param _address The address to convert.
|
|
382
|
+
function fromWormholeAddress(bytes32 _address)
|
|
383
|
+
public
|
|
384
|
+
pure
|
|
385
|
+
returns (address)
|
|
386
|
+
{
|
|
387
|
+
return address(uint160(uint256(_address)));
|
|
388
|
+
}
|
|
389
|
+
}
|
|
@@ -109,32 +109,32 @@
|
|
|
109
109
|
{
|
|
110
110
|
"ast": {
|
|
111
111
|
"nodeType": "YulBlock",
|
|
112
|
-
"src": "0:201:
|
|
112
|
+
"src": "0:201:123",
|
|
113
113
|
"statements": [
|
|
114
114
|
{
|
|
115
115
|
"nodeType": "YulBlock",
|
|
116
|
-
"src": "6:3:
|
|
116
|
+
"src": "6:3:123",
|
|
117
117
|
"statements": []
|
|
118
118
|
},
|
|
119
119
|
{
|
|
120
120
|
"body": {
|
|
121
121
|
"nodeType": "YulBlock",
|
|
122
|
-
"src": "123:76:
|
|
122
|
+
"src": "123:76:123",
|
|
123
123
|
"statements": [
|
|
124
124
|
{
|
|
125
125
|
"nodeType": "YulAssignment",
|
|
126
|
-
"src": "133:26:
|
|
126
|
+
"src": "133:26:123",
|
|
127
127
|
"value": {
|
|
128
128
|
"arguments": [
|
|
129
129
|
{
|
|
130
130
|
"name": "headStart",
|
|
131
131
|
"nodeType": "YulIdentifier",
|
|
132
|
-
"src": "145:9:
|
|
132
|
+
"src": "145:9:123"
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
135
|
"kind": "number",
|
|
136
136
|
"nodeType": "YulLiteral",
|
|
137
|
-
"src": "156:2:
|
|
137
|
+
"src": "156:2:123",
|
|
138
138
|
"type": "",
|
|
139
139
|
"value": "32"
|
|
140
140
|
}
|
|
@@ -142,16 +142,16 @@
|
|
|
142
142
|
"functionName": {
|
|
143
143
|
"name": "add",
|
|
144
144
|
"nodeType": "YulIdentifier",
|
|
145
|
-
"src": "141:3:
|
|
145
|
+
"src": "141:3:123"
|
|
146
146
|
},
|
|
147
147
|
"nodeType": "YulFunctionCall",
|
|
148
|
-
"src": "141:18:
|
|
148
|
+
"src": "141:18:123"
|
|
149
149
|
},
|
|
150
150
|
"variableNames": [
|
|
151
151
|
{
|
|
152
152
|
"name": "tail",
|
|
153
153
|
"nodeType": "YulIdentifier",
|
|
154
|
-
"src": "133:4:
|
|
154
|
+
"src": "133:4:123"
|
|
155
155
|
}
|
|
156
156
|
]
|
|
157
157
|
},
|
|
@@ -161,24 +161,24 @@
|
|
|
161
161
|
{
|
|
162
162
|
"name": "headStart",
|
|
163
163
|
"nodeType": "YulIdentifier",
|
|
164
|
-
"src": "175:9:
|
|
164
|
+
"src": "175:9:123"
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
167
|
"name": "value0",
|
|
168
168
|
"nodeType": "YulIdentifier",
|
|
169
|
-
"src": "186:6:
|
|
169
|
+
"src": "186:6:123"
|
|
170
170
|
}
|
|
171
171
|
],
|
|
172
172
|
"functionName": {
|
|
173
173
|
"name": "mstore",
|
|
174
174
|
"nodeType": "YulIdentifier",
|
|
175
|
-
"src": "168:6:
|
|
175
|
+
"src": "168:6:123"
|
|
176
176
|
},
|
|
177
177
|
"nodeType": "YulFunctionCall",
|
|
178
|
-
"src": "168:25:
|
|
178
|
+
"src": "168:25:123"
|
|
179
179
|
},
|
|
180
180
|
"nodeType": "YulExpressionStatement",
|
|
181
|
-
"src": "168:25:
|
|
181
|
+
"src": "168:25:123"
|
|
182
182
|
}
|
|
183
183
|
]
|
|
184
184
|
},
|
|
@@ -188,13 +188,13 @@
|
|
|
188
188
|
{
|
|
189
189
|
"name": "headStart",
|
|
190
190
|
"nodeType": "YulTypedName",
|
|
191
|
-
"src": "92:9:
|
|
191
|
+
"src": "92:9:123",
|
|
192
192
|
"type": ""
|
|
193
193
|
},
|
|
194
194
|
{
|
|
195
195
|
"name": "value0",
|
|
196
196
|
"nodeType": "YulTypedName",
|
|
197
|
-
"src": "103:6:
|
|
197
|
+
"src": "103:6:123",
|
|
198
198
|
"type": ""
|
|
199
199
|
}
|
|
200
200
|
],
|
|
@@ -202,16 +202,16 @@
|
|
|
202
202
|
{
|
|
203
203
|
"name": "tail",
|
|
204
204
|
"nodeType": "YulTypedName",
|
|
205
|
-
"src": "114:4:
|
|
205
|
+
"src": "114:4:123",
|
|
206
206
|
"type": ""
|
|
207
207
|
}
|
|
208
208
|
],
|
|
209
|
-
"src": "14:185:
|
|
209
|
+
"src": "14:185:123"
|
|
210
210
|
}
|
|
211
211
|
]
|
|
212
212
|
},
|
|
213
213
|
"contents": "{\n { }\n function abi_encode_tuple_t_uint256__to_t_uint256__fromStack_library_reversed(headStart, value0) -> tail\n {\n tail := add(headStart, 32)\n mstore(headStart, value0)\n }\n}",
|
|
214
|
-
"id":
|
|
214
|
+
"id": 123,
|
|
215
215
|
"language": "Yul",
|
|
216
216
|
"name": "#utility.yul"
|
|
217
217
|
}
|
|
@@ -219,7 +219,7 @@
|
|
|
219
219
|
"immutableReferences": {},
|
|
220
220
|
"linkReferences": {},
|
|
221
221
|
"opcodes": "PUSH20 0x0 ADDRESS EQ PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x51 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x56E04EC EQ PUSH1 0x56 JUMPI DUP1 PUSH4 0x8CC71569 EQ PUSH1 0x71 JUMPI DUP1 PUSH4 0x8DB69E60 EQ PUSH1 0x79 JUMPI DUP1 PUSH4 0xD4258CA7 EQ PUSH1 0x81 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x5F PUSH3 0x127500 DUP2 JUMP JUMPDEST PUSH1 0x40 MLOAD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x5F PUSH2 0x7E0 DUP2 JUMP JUMPDEST PUSH1 0x5F PUSH1 0x0 NOT DUP2 JUMP JUMPDEST PUSH1 0x5F PUSH28 0xFFFF0000000000000000000000000000000000000000000000000000 DUP2 JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 0x21 0xD8 0x5F GT 0xF6 0x4E 0xD4 0x4F 0xFB 0xA5 SWAP12 0xFC PUSH12 0x4A327F00D51E8E91CA784A04 DUP14 CALLDATACOPY 0x29 0xDB ADD 0xB3 PUSH32 0x64736F6C63430008110033000000000000000000000000000000000000000000 ",
|
|
222
|
-
"sourceMap": "175:38691:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;443:62;;485:20;443:62;;;;;168:25:
|
|
222
|
+
"sourceMap": "175:38691:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;443:62;;485:20;443:62;;;;;168:25:123;;;156:2;141:18;443:62:0;;;;;;;534:53;;583:4;534:53;;616:104;;-1:-1:-1;;616:104:0;;339:97;;378:58;339:97;"
|
|
223
223
|
},
|
|
224
224
|
"gasEstimates": {
|
|
225
225
|
"creation": {
|