@keep-network/tbtc-v2 0.1.1-dev.10 → 0.1.1-dev.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.adoc +12 -0
  2. package/artifacts/Bank.json +807 -0
  3. package/artifacts/Bridge.json +2300 -0
  4. package/artifacts/BridgeGovernance.json +2931 -0
  5. package/artifacts/BridgeGovernanceParameters.json +1445 -0
  6. package/artifacts/Deposit.json +117 -0
  7. package/artifacts/DepositSweep.json +77 -0
  8. package/artifacts/EcdsaDkgValidator.json +532 -0
  9. package/artifacts/EcdsaInactivity.json +156 -0
  10. package/artifacts/EcdsaSortitionPool.json +1004 -0
  11. package/artifacts/Fraud.json +164 -0
  12. package/artifacts/KeepRegistry.json +99 -0
  13. package/artifacts/KeepStake.json +286 -0
  14. package/artifacts/KeepToken.json +711 -0
  15. package/artifacts/KeepTokenStaking.json +483 -0
  16. package/artifacts/MaintainerProxy.json +1522 -0
  17. package/artifacts/MovingFunds.json +249 -0
  18. package/artifacts/NuCypherStakingEscrow.json +256 -0
  19. package/artifacts/NuCypherToken.json +711 -0
  20. package/artifacts/RandomBeaconStub.json +141 -0
  21. package/artifacts/Redemption.json +174 -0
  22. package/artifacts/ReimbursementPool.json +509 -0
  23. package/artifacts/Relay.json +123 -0
  24. package/artifacts/T.json +1148 -0
  25. package/artifacts/TBTC.json +27 -26
  26. package/artifacts/TBTCToken.json +27 -26
  27. package/artifacts/TBTCVault.json +691 -0
  28. package/artifacts/TokenStaking.json +2288 -0
  29. package/artifacts/TokenholderGovernor.json +1795 -0
  30. package/artifacts/TokenholderTimelock.json +1058 -0
  31. package/artifacts/VendingMachine.json +31 -30
  32. package/artifacts/VendingMachineKeep.json +400 -0
  33. package/artifacts/VendingMachineNuCypher.json +400 -0
  34. package/artifacts/WalletRegistry.json +1843 -0
  35. package/artifacts/WalletRegistryGovernance.json +2754 -0
  36. package/artifacts/Wallets.json +186 -0
  37. package/artifacts/solcInputs/f53bc10568b6d3c32d2989742aa1c456.json +323 -0
  38. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  39. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.json +2 -2
  40. package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
  41. package/build/contracts/bank/Bank.sol/Bank.json +10 -5
  42. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.dbg.json +4 -0
  43. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.json +34 -0
  44. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
  45. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +2 -2
  46. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
  47. package/build/contracts/bridge/Bridge.sol/Bridge.json +2549 -198
  48. package/build/contracts/bridge/BridgeGovernance.sol/BridgeGovernance.dbg.json +4 -0
  49. package/build/contracts/bridge/BridgeGovernance.sol/BridgeGovernance.json +2246 -0
  50. package/build/contracts/bridge/BridgeGovernanceParameters.sol/BridgeGovernanceParameters.dbg.json +4 -0
  51. package/build/contracts/bridge/BridgeGovernanceParameters.sol/BridgeGovernanceParameters.json +971 -0
  52. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +4 -0
  53. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +226 -0
  54. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +4 -0
  55. package/build/contracts/bridge/Deposit.sol/Deposit.json +72 -0
  56. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +4 -0
  57. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +30 -0
  58. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +4 -0
  59. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.json +10 -0
  60. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +4 -0
  61. package/build/contracts/bridge/Fraud.sol/Fraud.json +86 -0
  62. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.dbg.json +4 -0
  63. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.json +10 -0
  64. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +4 -0
  65. package/build/contracts/bridge/IRelay.sol/IRelay.json +37 -0
  66. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +4 -0
  67. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +138 -0
  68. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +4 -0
  69. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +10 -0
  70. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +4 -0
  71. package/build/contracts/bridge/Redemption.sol/Redemption.json +92 -0
  72. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  73. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.json +2 -2
  74. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +4 -0
  75. package/build/contracts/bridge/Wallets.sol/Wallets.json +112 -0
  76. package/build/contracts/maintainer/MaintainerProxy.sol/MaintainerProxy.dbg.json +4 -0
  77. package/build/contracts/maintainer/MaintainerProxy.sol/MaintainerProxy.json +1111 -0
  78. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  79. package/build/contracts/token/TBTC.sol/TBTC.json +2 -2
  80. package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +4 -0
  81. package/build/contracts/vault/DonationVault.sol/DonationVault.json +108 -0
  82. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  83. package/build/contracts/vault/IVault.sol/IVault.json +5 -0
  84. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  85. package/build/contracts/vault/TBTCVault.sol/TBTCVault.json +273 -5
  86. package/contracts/GovernanceUtils.sol +4 -4
  87. package/contracts/bank/Bank.sol +113 -66
  88. package/contracts/bank/IReceiveBalanceApproval.sol +45 -0
  89. package/contracts/bridge/BitcoinTx.sol +267 -10
  90. package/contracts/bridge/Bridge.sol +1698 -245
  91. package/contracts/bridge/BridgeGovernance.sol +1533 -0
  92. package/contracts/bridge/BridgeGovernanceParameters.sol +1695 -0
  93. package/contracts/bridge/BridgeState.sol +768 -0
  94. package/contracts/bridge/Deposit.sol +269 -0
  95. package/contracts/bridge/DepositSweep.sol +574 -0
  96. package/contracts/bridge/EcdsaLib.sol +45 -0
  97. package/contracts/bridge/Fraud.sol +579 -0
  98. package/contracts/bridge/Heartbeat.sol +112 -0
  99. package/contracts/bridge/IRelay.sol +28 -0
  100. package/contracts/bridge/MovingFunds.sol +1077 -0
  101. package/contracts/bridge/Redemption.sol +1058 -0
  102. package/contracts/bridge/VendingMachine.sol +2 -2
  103. package/contracts/bridge/Wallets.sol +719 -0
  104. package/contracts/hardhat-dependency-compiler/.hardhat-dependency-compiler +1 -0
  105. package/contracts/hardhat-dependency-compiler/@keep-network/ecdsa/contracts/WalletRegistry.sol +3 -0
  106. package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol +3 -0
  107. package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol +3 -0
  108. package/contracts/maintainer/MaintainerProxy.sol +512 -0
  109. package/contracts/token/TBTC.sol +1 -1
  110. package/contracts/vault/DonationVault.sol +125 -0
  111. package/contracts/vault/IVault.sol +6 -22
  112. package/contracts/vault/TBTCVault.sol +188 -29
  113. package/deploy/00_resolve_relay.ts +28 -0
  114. package/deploy/{03_transfer_roles.ts → 03_transfer_vending_machine_roles.ts} +1 -1
  115. package/deploy/04_deploy_bank.ts +27 -0
  116. package/deploy/05_deploy_bridge.ts +80 -0
  117. package/deploy/06_deploy_tbtc_vault.ts +30 -0
  118. package/deploy/07_deploy_bridge_governance.ts +40 -0
  119. package/deploy/08_deploy_maintainer_proxy.ts +30 -0
  120. package/deploy/09_bank_update_bridge.ts +19 -0
  121. package/deploy/10_transfer_bank_ownership.ts +15 -0
  122. package/deploy/11_transfer_bridge_governance.ts +22 -0
  123. package/deploy/12_transfer_bridge_governance_ownership.ts +19 -0
  124. package/deploy/13_transfer_tbtc_vault_ownership.ts +15 -0
  125. package/deploy/14_transfer_maintainer_proxy_ownership.ts +19 -0
  126. package/deploy/15_initialize_wallet_owner.ts +18 -0
  127. package/deploy/16_transfer_proxy_admin_ownership.ts +30 -0
  128. package/deploy/17_authorize_maintainer_proxy.ts +22 -0
  129. package/deploy/18_transfer_reimbursement_pool_ownership.ts +19 -0
  130. package/deploy/19_deploy_proxy_admin_with_deputy.ts +33 -0
  131. package/export.json +19544 -404
  132. package/package.json +34 -26
  133. package/artifacts/solcInputs/524094faac10a04084fcc411e06dab84.json +0 -128
@@ -0,0 +1 @@
1
+ directory approved for write access by hardhat-dependency-compiler
@@ -0,0 +1,3 @@
1
+ // SPDX-License-Identifier: UNLICENSED
2
+ pragma solidity >0.0.0;
3
+ import '@keep-network/ecdsa/contracts/WalletRegistry.sol';
@@ -0,0 +1,3 @@
1
+ // SPDX-License-Identifier: UNLICENSED
2
+ pragma solidity >0.0.0;
3
+ import '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol';
@@ -0,0 +1,3 @@
1
+ // SPDX-License-Identifier: UNLICENSED
2
+ pragma solidity >0.0.0;
3
+ import '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol';
@@ -0,0 +1,512 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ // ██████████████ ▐████▌ ██████████████
4
+ // ██████████████ ▐████▌ ██████████████
5
+ // ▐████▌ ▐████▌
6
+ // ▐████▌ ▐████▌
7
+ // ██████████████ ▐████▌ ██████████████
8
+ // ██████████████ ▐████▌ ██████████████
9
+ // ▐████▌ ▐████▌
10
+ // ▐████▌ ▐████▌
11
+ // ▐████▌ ▐████▌
12
+ // ▐████▌ ▐████▌
13
+ // ▐████▌ ▐████▌
14
+ // ▐████▌ ▐████▌
15
+
16
+ pragma solidity ^0.8.9;
17
+
18
+ import "@openzeppelin/contracts/access/Ownable.sol";
19
+ import "@keep-network/random-beacon/contracts/Reimbursable.sol";
20
+ import "@keep-network/random-beacon/contracts/ReimbursementPool.sol";
21
+
22
+ import "../bridge/BitcoinTx.sol";
23
+ import "../bridge/Bridge.sol";
24
+
25
+ /// @title Maintainer Proxy
26
+ /// @notice Maintainers are the willing off-chain clients approved by the governance.
27
+ /// Maintainers proxy calls to the Bridge contract via 'MaintainerProxy'
28
+ /// and are refunded for the spent gas from the Reimbursement Pool.
29
+ /// Only the authorized maintainers can call 'MaintainerProxy' functions.
30
+ contract MaintainerProxy is Ownable, Reimbursable {
31
+ Bridge public bridge;
32
+
33
+ /// @notice Authorized maintainers that can interact with the set of functions
34
+ /// for maintainers only. Authorization can be granted and removed by
35
+ /// the governance.
36
+ /// @dev 'Key' is the address of the maintainer. 'Value' represents an index+1
37
+ /// in the 'maintainers' array. 1 was added so the maintainer index can
38
+ /// never be 0 which is a reserved index for a non-existent maintainer
39
+ /// in this map.
40
+ mapping(address => uint256) public isAuthorized;
41
+
42
+ /// @notice This list of maintainers keeps the order of which maintainer should
43
+ /// be submitting a next transaction. It does not enforce the order
44
+ /// but only tracks who should be next in line.
45
+ address[] public maintainers;
46
+
47
+ /// @notice Gas that is meant to balance the submission of deposit sweep proof
48
+ /// overall cost. Can be updated by the governance based on the current
49
+ /// market conditions.
50
+ uint256 public submitDepositSweepProofGasOffset;
51
+
52
+ /// @notice Gas that is meant to balance the submission of redemption proof
53
+ /// overall cost. Can be updated by the governance based on the current
54
+ /// market conditions.
55
+ uint256 public submitRedemptionProofGasOffset;
56
+
57
+ /// @notice Gas that is meant to balance the submission of moving funds commitment
58
+ /// overall cost. Can be updated by the governance based on the current
59
+ /// market conditions.
60
+ uint256 public submitMovingFundsCommitmentGasOffset;
61
+
62
+ /// @notice Gas that is meant to balance the reset of moving funds timeout
63
+ /// overall cost. Can be updated by the governance based on the current
64
+ /// market conditions.
65
+ uint256 public resetMovingFundsTimeoutGasOffset;
66
+
67
+ /// @notice Gas that is meant to balance the submission of moving funds proof
68
+ /// overall cost. Can be updated by the governance based on the current
69
+ /// market conditions.
70
+ uint256 public submitMovingFundsProofGasOffset;
71
+
72
+ /// @notice Gas that is meant to balance the notification of moving funds below
73
+ /// dust overall cost. Can be updated by the governance based on the
74
+ /// current market conditions.
75
+ uint256 public notifyMovingFundsBelowDustGasOffset;
76
+
77
+ /// @notice Gas that is meant to balance the submission of moved funds sweep
78
+ /// proof overall cost. Can be updated by the governance based on the
79
+ /// current market conditions.
80
+ uint256 public submitMovedFundsSweepProofGasOffset;
81
+
82
+ /// @notice Gas that is meant to balance the request of a new wallet overall
83
+ /// cost. Can be updated by the governance based on the current
84
+ /// market conditions.
85
+ uint256 public requestNewWalletGasOffset;
86
+
87
+ /// @notice Gas that is meant to balance the notification of closeable wallet
88
+ /// overall cost. Can be updated by the governance based on the current
89
+ /// market conditions.
90
+ uint256 public notifyWalletCloseableGasOffset;
91
+
92
+ /// @notice Gas that is meant to balance the notification of wallet closing
93
+ /// period elapsed overall cost. Can be updated by the governance
94
+ /// based on the current market conditions.
95
+ uint256 public notifyWalletClosingPeriodElapsedGasOffset;
96
+
97
+ /// @notice Gas that is meant to balance the defeat fraud challenge
98
+ /// overall cost. Can be updated by the governance based on the current
99
+ /// market conditions.
100
+ uint256 public defeatFraudChallengeGasOffset;
101
+
102
+ /// @notice Gas that is meant to balance the defeat fraud challenge with heartbeat
103
+ /// overall cost. Can be updated by the governance based on the current
104
+ /// market conditions.
105
+ uint256 public defeatFraudChallengeWithHeartbeatGasOffset;
106
+
107
+ event MaintainerAuthorized(address indexed maintainer);
108
+
109
+ event MaintainerUnauthorized(address indexed maintainer);
110
+
111
+ event BridgeUpdated(address newBridge);
112
+
113
+ event GasOffsetParametersUpdated(
114
+ uint256 submitDepositSweepProofGasOffset,
115
+ uint256 submitRedemptionProofGasOffset,
116
+ uint256 submitMovingFundsCommitmentGasOffset,
117
+ uint256 resetMovingFundsTimeoutGasOffset,
118
+ uint256 submitMovingFundsProofGasOffset,
119
+ uint256 notifyMovingFundsBelowDustGasOffset,
120
+ uint256 submitMovedFundsSweepProofGasOffset,
121
+ uint256 requestNewWalletGasOffset,
122
+ uint256 notifyWalletCloseableGasOffset,
123
+ uint256 notifyWalletClosingPeriodElapsedGasOffset,
124
+ uint256 defeatFraudChallengeGasOffset,
125
+ uint256 defeatFraudChallengeWithHeartbeatGasOffset
126
+ );
127
+
128
+ modifier onlyMaintainer() {
129
+ require(isAuthorized[msg.sender] != 0, "Caller is not authorized");
130
+ _;
131
+ }
132
+
133
+ modifier onlyReimbursableAdmin() override {
134
+ require(owner() == msg.sender, "Caller is not the owner");
135
+ _;
136
+ }
137
+
138
+ constructor(Bridge _bridge, ReimbursementPool _reimbursementPool) {
139
+ bridge = _bridge;
140
+ reimbursementPool = _reimbursementPool;
141
+ submitDepositSweepProofGasOffset = 27000;
142
+ submitRedemptionProofGasOffset = 9750;
143
+ submitMovingFundsCommitmentGasOffset = 8000;
144
+ resetMovingFundsTimeoutGasOffset = 1000;
145
+ submitMovingFundsProofGasOffset = 15000;
146
+ notifyMovingFundsBelowDustGasOffset = 3500;
147
+ submitMovedFundsSweepProofGasOffset = 22000;
148
+ requestNewWalletGasOffset = 3500;
149
+ notifyWalletCloseableGasOffset = 4000;
150
+ notifyWalletClosingPeriodElapsedGasOffset = 3000;
151
+ defeatFraudChallengeGasOffset = 10000;
152
+ defeatFraudChallengeWithHeartbeatGasOffset = 5000;
153
+ }
154
+
155
+ /// @notice Wraps `Bridge.submitDepositSweepProof` call and reimburses the
156
+ /// caller's transaction cost.
157
+ /// @dev See `Bridge.submitDepositSweepProof` function documentation.
158
+ function submitDepositSweepProof(
159
+ BitcoinTx.Info calldata sweepTx,
160
+ BitcoinTx.Proof calldata sweepProof,
161
+ BitcoinTx.UTXO calldata mainUtxo,
162
+ address vault
163
+ ) external onlyMaintainer {
164
+ uint256 gasStart = gasleft();
165
+
166
+ bridge.submitDepositSweepProof(sweepTx, sweepProof, mainUtxo, vault);
167
+
168
+ reimbursementPool.refund(
169
+ (gasStart - gasleft()) + submitDepositSweepProofGasOffset,
170
+ msg.sender
171
+ );
172
+ }
173
+
174
+ /// @notice Wraps `Bridge.submitRedemptionProof` call and reimburses the
175
+ /// caller's transaction cost.
176
+ /// @dev See `Bridge.submitRedemptionProof` function documentation.
177
+ function submitRedemptionProof(
178
+ BitcoinTx.Info calldata redemptionTx,
179
+ BitcoinTx.Proof calldata redemptionProof,
180
+ BitcoinTx.UTXO calldata mainUtxo,
181
+ bytes20 walletPubKeyHash
182
+ ) external onlyMaintainer {
183
+ uint256 gasStart = gasleft();
184
+
185
+ bridge.submitRedemptionProof(
186
+ redemptionTx,
187
+ redemptionProof,
188
+ mainUtxo,
189
+ walletPubKeyHash
190
+ );
191
+
192
+ reimbursementPool.refund(
193
+ (gasStart - gasleft()) + submitRedemptionProofGasOffset,
194
+ msg.sender
195
+ );
196
+ }
197
+
198
+ /// @notice Wraps `Bridge.submitMovingFundsCommitment` call and reimburses the
199
+ /// caller's transaction cost.
200
+ /// @dev See `Bridge.submitMovingFundsCommitment` function documentation.
201
+ function submitMovingFundsCommitment(
202
+ bytes20 walletPubKeyHash,
203
+ BitcoinTx.UTXO calldata walletMainUtxo,
204
+ uint32[] calldata walletMembersIDs,
205
+ uint256 walletMemberIndex,
206
+ bytes20[] calldata targetWallets
207
+ ) external {
208
+ uint256 gasStart = gasleft();
209
+
210
+ bridge.submitMovingFundsCommitment(
211
+ walletPubKeyHash,
212
+ walletMainUtxo,
213
+ walletMembersIDs,
214
+ walletMemberIndex,
215
+ targetWallets
216
+ );
217
+
218
+ reimbursementPool.refund(
219
+ (gasStart - gasleft()) + submitMovingFundsCommitmentGasOffset,
220
+ msg.sender
221
+ );
222
+ }
223
+
224
+ /// @notice Wraps `Bridge.resetMovingFundsTimeout` call and reimburses the
225
+ /// caller's transaction cost.
226
+ /// @dev See `Bridge.resetMovingFundsTimeout` function documentation.
227
+ function resetMovingFundsTimeout(bytes20 walletPubKeyHash) external {
228
+ uint256 gasStart = gasleft();
229
+
230
+ bridge.resetMovingFundsTimeout(walletPubKeyHash);
231
+
232
+ reimbursementPool.refund(
233
+ (gasStart - gasleft()) + resetMovingFundsTimeoutGasOffset,
234
+ msg.sender
235
+ );
236
+ }
237
+
238
+ /// @notice Wraps `Bridge.submitMovingFundsProof` call and reimburses the
239
+ /// caller's transaction cost.
240
+ /// @dev See `Bridge.submitMovingFundsProof` function documentation.
241
+ function submitMovingFundsProof(
242
+ BitcoinTx.Info calldata movingFundsTx,
243
+ BitcoinTx.Proof calldata movingFundsProof,
244
+ BitcoinTx.UTXO calldata mainUtxo,
245
+ bytes20 walletPubKeyHash
246
+ ) external onlyMaintainer {
247
+ uint256 gasStart = gasleft();
248
+
249
+ bridge.submitMovingFundsProof(
250
+ movingFundsTx,
251
+ movingFundsProof,
252
+ mainUtxo,
253
+ walletPubKeyHash
254
+ );
255
+
256
+ reimbursementPool.refund(
257
+ (gasStart - gasleft()) + submitMovingFundsProofGasOffset,
258
+ msg.sender
259
+ );
260
+ }
261
+
262
+ /// @notice Wraps `Bridge.notifyMovingFundsBelowDust` call and reimburses the
263
+ /// caller's transaction cost.
264
+ /// @dev See `Bridge.notifyMovingFundsBelowDust` function documentation.
265
+ function notifyMovingFundsBelowDust(
266
+ bytes20 walletPubKeyHash,
267
+ BitcoinTx.UTXO calldata mainUtxo
268
+ ) external onlyMaintainer {
269
+ uint256 gasStart = gasleft();
270
+
271
+ bridge.notifyMovingFundsBelowDust(walletPubKeyHash, mainUtxo);
272
+
273
+ reimbursementPool.refund(
274
+ (gasStart - gasleft()) + notifyMovingFundsBelowDustGasOffset,
275
+ msg.sender
276
+ );
277
+ }
278
+
279
+ /// @notice Wraps `Bridge.submitMovedFundsSweepProof` call and reimburses the
280
+ /// caller's transaction cost.
281
+ /// @dev See `Bridge.submitMovedFundsSweepProof` function documentation.
282
+ function submitMovedFundsSweepProof(
283
+ BitcoinTx.Info calldata sweepTx,
284
+ BitcoinTx.Proof calldata sweepProof,
285
+ BitcoinTx.UTXO calldata mainUtxo
286
+ ) external onlyMaintainer {
287
+ uint256 gasStart = gasleft();
288
+
289
+ bridge.submitMovedFundsSweepProof(sweepTx, sweepProof, mainUtxo);
290
+
291
+ reimbursementPool.refund(
292
+ (gasStart - gasleft()) + submitMovedFundsSweepProofGasOffset,
293
+ msg.sender
294
+ );
295
+ }
296
+
297
+ /// @notice Wraps `Bridge.requestNewWallet` call and reimburses the
298
+ /// caller's transaction cost.
299
+ /// @dev See `Bridge.requestNewWallet` function documentation.
300
+ function requestNewWallet(BitcoinTx.UTXO calldata activeWalletMainUtxo)
301
+ external
302
+ onlyMaintainer
303
+ {
304
+ uint256 gasStart = gasleft();
305
+
306
+ bridge.requestNewWallet(activeWalletMainUtxo);
307
+
308
+ reimbursementPool.refund(
309
+ (gasStart - gasleft()) + requestNewWalletGasOffset,
310
+ msg.sender
311
+ );
312
+ }
313
+
314
+ /// @notice Wraps `Bridge.notifyWalletCloseable` call and reimburses the
315
+ /// caller's transaction cost.
316
+ /// @dev See `Bridge.notifyWalletCloseable` function documentation.
317
+ function notifyWalletCloseable(
318
+ bytes20 walletPubKeyHash,
319
+ BitcoinTx.UTXO calldata walletMainUtxo
320
+ ) external onlyMaintainer {
321
+ uint256 gasStart = gasleft();
322
+
323
+ bridge.notifyWalletCloseable(walletPubKeyHash, walletMainUtxo);
324
+
325
+ reimbursementPool.refund(
326
+ (gasStart - gasleft()) + notifyWalletCloseableGasOffset,
327
+ msg.sender
328
+ );
329
+ }
330
+
331
+ /// @notice Wraps `Bridge.notifyWalletClosingPeriodElapsed` call and reimburses
332
+ /// the caller's transaction cost.
333
+ /// @dev See `Bridge.notifyWalletClosingPeriodElapsed` function documentation.
334
+ function notifyWalletClosingPeriodElapsed(bytes20 walletPubKeyHash)
335
+ external
336
+ onlyMaintainer
337
+ {
338
+ uint256 gasStart = gasleft();
339
+
340
+ bridge.notifyWalletClosingPeriodElapsed(walletPubKeyHash);
341
+
342
+ reimbursementPool.refund(
343
+ (gasStart - gasleft()) + notifyWalletClosingPeriodElapsedGasOffset,
344
+ msg.sender
345
+ );
346
+ }
347
+
348
+ /// @notice Wraps `Bridge.defeatFraudChallenge` call and reimburses the
349
+ /// caller's transaction cost.
350
+ /// @dev See `Bridge.defeatFraudChallenge` function documentation.
351
+ function defeatFraudChallenge(
352
+ bytes calldata walletPublicKey,
353
+ bytes calldata preimage,
354
+ bool witness
355
+ ) external {
356
+ uint256 gasStart = gasleft();
357
+
358
+ bridge.defeatFraudChallenge(walletPublicKey, preimage, witness);
359
+
360
+ reimbursementPool.refund(
361
+ (gasStart - gasleft()) + defeatFraudChallengeGasOffset,
362
+ msg.sender
363
+ );
364
+ }
365
+
366
+ /// @notice Wraps `Bridge.defeatFraudChallengeWithHeartbeat` call and
367
+ /// reimburses the caller's transaction cost.
368
+ /// @dev See `Bridge.defeatFraudChallengeWithHeartbeat` function documentation.
369
+ function defeatFraudChallengeWithHeartbeat(
370
+ bytes calldata walletPublicKey,
371
+ bytes calldata heartbeatMessage
372
+ ) external {
373
+ uint256 gasStart = gasleft();
374
+
375
+ bridge.defeatFraudChallengeWithHeartbeat(
376
+ walletPublicKey,
377
+ heartbeatMessage
378
+ );
379
+
380
+ reimbursementPool.refund(
381
+ (gasStart - gasleft()) + defeatFraudChallengeWithHeartbeatGasOffset,
382
+ msg.sender
383
+ );
384
+ }
385
+
386
+ /// @notice Authorize a maintainer that can interact with this reimbursement pool.
387
+ /// Can be authorized by the owner only.
388
+ /// @param maintainer Maintainer to authorize.
389
+ function authorize(address maintainer) external onlyOwner {
390
+ maintainers.push(maintainer);
391
+ isAuthorized[maintainer] = maintainers.length;
392
+
393
+ emit MaintainerAuthorized(maintainer);
394
+ }
395
+
396
+ /// @notice Unauthorize a maintainer that was previously authorized to interact
397
+ /// with the Maintainer Proxy contract. Can be unauthorized by the
398
+ /// owner only.
399
+ /// @dev The last maintainer is swapped with the one to be unauthorized.
400
+ /// The unauthorized maintainer is then removed from the list. An index
401
+ /// of the last maintainer is changed with the removed maintainer.
402
+ /// Ex.
403
+ /// 'maintainers' list: [0x1, 0x2, 0x3, 0x4, 0x5]
404
+ /// 'isAuthorized' map: [0x1 -> 1, 0x2 -> 2, 0x3 -> 3, 0x4 -> 4, 0x5 -> 5]
405
+ /// unauthorize: 0x3
406
+ /// new 'maintainers' list: [0x1, 0x2, 0x5, 0x4]
407
+ /// new 'isAuthorized' map: [0x1 -> 1, 0x2 -> 2, 0x4 -> 4, 0x5 -> 3]
408
+ /// @param maintainerToUnauthorize Maintainer to unauthorize.
409
+ function unauthorize(address maintainerToUnauthorize) external onlyOwner {
410
+ uint256 maintainerIdToUnauthorize = isAuthorized[
411
+ maintainerToUnauthorize
412
+ ];
413
+
414
+ require(maintainerIdToUnauthorize != 0, "No maintainer to unauthorize");
415
+
416
+ address lastMaintainerAddress = maintainers[maintainers.length - 1];
417
+
418
+ maintainers[maintainerIdToUnauthorize - 1] = lastMaintainerAddress;
419
+ maintainers.pop();
420
+
421
+ isAuthorized[lastMaintainerAddress] = maintainerIdToUnauthorize;
422
+
423
+ delete isAuthorized[maintainerToUnauthorize];
424
+
425
+ emit MaintainerUnauthorized(maintainerToUnauthorize);
426
+ }
427
+
428
+ /// @notice Allows the Governance to upgrade the Bridge address.
429
+ /// @dev The function does not implement any governance delay and does not
430
+ /// check the status of the Bridge. The Governance implementation needs
431
+ /// to ensure all requirements for the upgrade are satisfied before
432
+ /// executing this function.
433
+ function updateBridge(Bridge _bridge) external onlyOwner {
434
+ bridge = _bridge;
435
+
436
+ emit BridgeUpdated(address(_bridge));
437
+ }
438
+
439
+ /// @notice Updates the values of gas offset parameters.
440
+ /// @dev Can be called only by the contract owner. The caller is responsible
441
+ /// for validating parameters.
442
+ /// @param newSubmitDepositSweepProofGasOffset New submit deposit sweep
443
+ /// proof gas offset.
444
+ /// @param newSubmitRedemptionProofGasOffset New submit redemption proof gas
445
+ /// offset.
446
+ /// @param newSubmitMovingFundsCommitmentGasOffset New submit moving funds
447
+ /// commitment gas offset.
448
+ /// @param newResetMovingFundsTimeoutGasOffset New reset moving funds
449
+ /// timeout gas offset.
450
+ /// @param newSubmitMovingFundsProofGasOffset New submit moving funds proof
451
+ /// gas offset.
452
+ /// @param newNotifyMovingFundsBelowDustGasOffset New notify moving funds
453
+ /// below dust gas offset.
454
+ /// @param newSubmitMovedFundsSweepProofGasOffset New submit moved funds
455
+ /// sweep proof gas offset.
456
+ /// @param newRequestNewWalletGasOffset New request new wallet gas offset.
457
+ /// @param newNotifyWalletCloseableGasOffset New notify closeable wallet gas
458
+ /// offset.
459
+ /// @param newNotifyWalletClosingPeriodElapsedGasOffset New notify wallet
460
+ /// closing period elapsed gas offset.
461
+ /// @param newDefeatFraudChallengeGasOffset New defeat fraud challenge gas
462
+ /// offset.
463
+ /// @param newDefeatFraudChallengeWithHeartbeatGasOffset New defeat fraud
464
+ /// challenge with heartbeat gas offset.
465
+ function updateGasOffsetParameters(
466
+ uint256 newSubmitDepositSweepProofGasOffset,
467
+ uint256 newSubmitRedemptionProofGasOffset,
468
+ uint256 newSubmitMovingFundsCommitmentGasOffset,
469
+ uint256 newResetMovingFundsTimeoutGasOffset,
470
+ uint256 newSubmitMovingFundsProofGasOffset,
471
+ uint256 newNotifyMovingFundsBelowDustGasOffset,
472
+ uint256 newSubmitMovedFundsSweepProofGasOffset,
473
+ uint256 newRequestNewWalletGasOffset,
474
+ uint256 newNotifyWalletCloseableGasOffset,
475
+ uint256 newNotifyWalletClosingPeriodElapsedGasOffset,
476
+ uint256 newDefeatFraudChallengeGasOffset,
477
+ uint256 newDefeatFraudChallengeWithHeartbeatGasOffset
478
+ ) external onlyOwner {
479
+ submitDepositSweepProofGasOffset = newSubmitDepositSweepProofGasOffset;
480
+ submitRedemptionProofGasOffset = newSubmitRedemptionProofGasOffset;
481
+ submitMovingFundsCommitmentGasOffset = newSubmitMovingFundsCommitmentGasOffset;
482
+ resetMovingFundsTimeoutGasOffset = newResetMovingFundsTimeoutGasOffset;
483
+ submitMovingFundsProofGasOffset = newSubmitMovingFundsProofGasOffset;
484
+ notifyMovingFundsBelowDustGasOffset = newNotifyMovingFundsBelowDustGasOffset;
485
+ submitMovedFundsSweepProofGasOffset = newSubmitMovedFundsSweepProofGasOffset;
486
+ requestNewWalletGasOffset = newRequestNewWalletGasOffset;
487
+ notifyWalletCloseableGasOffset = newNotifyWalletCloseableGasOffset;
488
+ notifyWalletClosingPeriodElapsedGasOffset = newNotifyWalletClosingPeriodElapsedGasOffset;
489
+ defeatFraudChallengeGasOffset = newDefeatFraudChallengeGasOffset;
490
+ defeatFraudChallengeWithHeartbeatGasOffset = newDefeatFraudChallengeWithHeartbeatGasOffset;
491
+
492
+ emit GasOffsetParametersUpdated(
493
+ submitDepositSweepProofGasOffset,
494
+ submitRedemptionProofGasOffset,
495
+ submitMovingFundsCommitmentGasOffset,
496
+ resetMovingFundsTimeoutGasOffset,
497
+ submitMovingFundsProofGasOffset,
498
+ notifyMovingFundsBelowDustGasOffset,
499
+ submitMovedFundsSweepProofGasOffset,
500
+ requestNewWalletGasOffset,
501
+ notifyWalletCloseableGasOffset,
502
+ notifyWalletClosingPeriodElapsedGasOffset,
503
+ defeatFraudChallengeGasOffset,
504
+ defeatFraudChallengeWithHeartbeatGasOffset
505
+ );
506
+ }
507
+
508
+ /// @notice Gets an entire array of maintainer addresses.
509
+ function allMaintainers() external view returns (address[] memory) {
510
+ return maintainers;
511
+ }
512
+ }
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
 
3
- pragma solidity 0.8.4;
3
+ pragma solidity ^0.8.9;
4
4
 
5
5
  import "@thesis/solidity-contracts/contracts/token/ERC20WithPermit.sol";
6
6
  import "@thesis/solidity-contracts/contracts/token/MisfundRecovery.sol";
@@ -0,0 +1,125 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ // ██████████████ ▐████▌ ██████████████
4
+ // ██████████████ ▐████▌ ██████████████
5
+ // ▐████▌ ▐████▌
6
+ // ▐████▌ ▐████▌
7
+ // ██████████████ ▐████▌ ██████████████
8
+ // ██████████████ ▐████▌ ██████████████
9
+ // ▐████▌ ▐████▌
10
+ // ▐████▌ ▐████▌
11
+ // ▐████▌ ▐████▌
12
+ // ▐████▌ ▐████▌
13
+ // ▐████▌ ▐████▌
14
+ // ▐████▌ ▐████▌
15
+
16
+ pragma solidity ^0.8.9;
17
+
18
+ import "./IVault.sol";
19
+ import "../bank/Bank.sol";
20
+
21
+ /// @title BTC donation vault
22
+ /// @notice Vault that allows making BTC donations to the system. Upon deposit,
23
+ /// this vault does not increase depositors' balances and always
24
+ /// decreases its own balance in the same transaction. The vault also
25
+ /// allows making donations using existing Bank balances.
26
+ ///
27
+ /// BEWARE: ALL BTC DEPOSITS TARGETING THIS VAULT ARE NOT REDEEMABLE
28
+ /// AND THERE IS NO WAY TO RESTORE THE DONATED BALANCE.
29
+ /// USE THIS VAULT ONLY WHEN YOU REALLY KNOW WHAT YOU ARE DOING!
30
+ contract DonationVault is IVault {
31
+ Bank public bank;
32
+
33
+ event DonationReceived(address donor, uint256 donatedAmount);
34
+
35
+ modifier onlyBank() {
36
+ require(msg.sender == address(bank), "Caller is not the Bank");
37
+ _;
38
+ }
39
+
40
+ constructor(Bank _bank) {
41
+ require(
42
+ address(_bank) != address(0),
43
+ "Bank can not be the zero address"
44
+ );
45
+
46
+ bank = _bank;
47
+ }
48
+
49
+ /// @notice Transfers the given `amount` of the Bank balance from the
50
+ /// caller to the Donation Vault and immediately decreases the
51
+ /// vault's balance in the Bank by the transferred `amount`.
52
+ /// @param amount Amount of the Bank balance to donate.
53
+ /// @dev Requirements:
54
+ /// - The caller's balance in the Bank must be greater than or equal
55
+ /// to the `amount`,
56
+ /// - Donation Vault must have an allowance for caller's balance in
57
+ /// the Bank for at least `amount`.
58
+ function donate(uint256 amount) external {
59
+ address donor = msg.sender;
60
+
61
+ require(
62
+ bank.balanceOf(donor) >= amount,
63
+ "Amount exceeds balance in the bank"
64
+ );
65
+
66
+ emit DonationReceived(donor, amount);
67
+
68
+ bank.transferBalanceFrom(donor, address(this), amount);
69
+ bank.decreaseBalance(amount);
70
+ }
71
+
72
+ /// @notice Transfers the given `amount` of the Bank balance from the
73
+ /// `owner` to the Donation Vault and immediately decreases the
74
+ /// vault's balance in the Bank by the transferred `amount`.
75
+ /// @param owner Address of the Bank balance owner who approved their
76
+ /// balance to be used by the vault.
77
+ /// @param amount The amount of the Bank balance approved by the owner
78
+ /// to be used by the vault.
79
+ /// @dev Requirements:
80
+ /// - Can only be called by the Bank via `approveBalanceAndCall`,
81
+ /// - The `owner` balance in the Bank must be greater than or equal
82
+ /// to the `amount`.
83
+ function receiveBalanceApproval(
84
+ address owner,
85
+ uint256 amount,
86
+ bytes memory
87
+ ) external override onlyBank {
88
+ require(
89
+ bank.balanceOf(owner) >= amount,
90
+ "Amount exceeds balance in the bank"
91
+ );
92
+
93
+ emit DonationReceived(owner, amount);
94
+
95
+ bank.transferBalanceFrom(owner, address(this), amount);
96
+ bank.decreaseBalance(amount);
97
+ }
98
+
99
+ /// @notice Ignores the deposited amounts and does not increase depositors'
100
+ /// individual balances. The vault decreases its own tBTC balance
101
+ /// in the Bank by the total deposited amount.
102
+ /// @param depositors Addresses of depositors whose deposits have been swept.
103
+ /// @param depositedAmounts Amounts deposited by individual depositors and
104
+ /// swept.
105
+ /// @dev Requirements:
106
+ /// - Can only be called by the Bank after the Bridge swept deposits
107
+ /// and Bank increased balance for the vault,
108
+ /// - The `depositors` array must not be empty,
109
+ /// - The `depositors` array length must be equal to the
110
+ /// `depositedAmounts` array length.
111
+ function receiveBalanceIncrease(
112
+ address[] calldata depositors,
113
+ uint256[] calldata depositedAmounts
114
+ ) external override onlyBank {
115
+ require(depositors.length != 0, "No depositors specified");
116
+
117
+ uint256 totalAmount = 0;
118
+ for (uint256 i = 0; i < depositors.length; i++) {
119
+ totalAmount += depositedAmounts[i];
120
+ emit DonationReceived(depositors[i], depositedAmounts[i]);
121
+ }
122
+
123
+ bank.decreaseBalance(totalAmount);
124
+ }
125
+ }