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

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 (115) 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/Deposit.json +117 -0
  5. package/artifacts/DepositSweep.json +77 -0
  6. package/artifacts/EcdsaDkgValidator.json +532 -0
  7. package/artifacts/EcdsaInactivity.json +156 -0
  8. package/artifacts/EcdsaSortitionPool.json +1004 -0
  9. package/artifacts/Fraud.json +164 -0
  10. package/artifacts/KeepRegistry.json +99 -0
  11. package/artifacts/KeepStake.json +286 -0
  12. package/artifacts/KeepToken.json +711 -0
  13. package/artifacts/KeepTokenStaking.json +483 -0
  14. package/artifacts/MovingFunds.json +249 -0
  15. package/artifacts/NuCypherStakingEscrow.json +256 -0
  16. package/artifacts/NuCypherToken.json +711 -0
  17. package/artifacts/RandomBeaconStub.json +141 -0
  18. package/artifacts/Redemption.json +174 -0
  19. package/artifacts/ReimbursementPool.json +509 -0
  20. package/artifacts/Relay.json +123 -0
  21. package/artifacts/T.json +1148 -0
  22. package/artifacts/TBTC.json +27 -26
  23. package/artifacts/TBTCToken.json +27 -26
  24. package/artifacts/TBTCVault.json +691 -0
  25. package/artifacts/TokenStaking.json +2288 -0
  26. package/artifacts/TokenholderGovernor.json +1795 -0
  27. package/artifacts/TokenholderTimelock.json +1058 -0
  28. package/artifacts/VendingMachine.json +31 -30
  29. package/artifacts/VendingMachineKeep.json +400 -0
  30. package/artifacts/VendingMachineNuCypher.json +400 -0
  31. package/artifacts/WalletRegistry.json +1843 -0
  32. package/artifacts/WalletRegistryGovernance.json +2754 -0
  33. package/artifacts/Wallets.json +186 -0
  34. package/artifacts/solcInputs/8b65103759482b36742c6820fa66b63b.json +314 -0
  35. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  36. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.json +2 -2
  37. package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
  38. package/build/contracts/bank/Bank.sol/Bank.json +10 -5
  39. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.dbg.json +4 -0
  40. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.json +34 -0
  41. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
  42. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +2 -2
  43. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
  44. package/build/contracts/bridge/Bridge.sol/Bridge.json +2549 -198
  45. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +4 -0
  46. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +226 -0
  47. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +4 -0
  48. package/build/contracts/bridge/Deposit.sol/Deposit.json +72 -0
  49. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +4 -0
  50. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +30 -0
  51. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +4 -0
  52. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.json +10 -0
  53. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +4 -0
  54. package/build/contracts/bridge/Fraud.sol/Fraud.json +86 -0
  55. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.dbg.json +4 -0
  56. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.json +10 -0
  57. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +4 -0
  58. package/build/contracts/bridge/IRelay.sol/IRelay.json +37 -0
  59. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +4 -0
  60. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +138 -0
  61. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +4 -0
  62. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +10 -0
  63. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +4 -0
  64. package/build/contracts/bridge/Redemption.sol/Redemption.json +92 -0
  65. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  66. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.json +2 -2
  67. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +4 -0
  68. package/build/contracts/bridge/Wallets.sol/Wallets.json +112 -0
  69. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  70. package/build/contracts/token/TBTC.sol/TBTC.json +2 -2
  71. package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +4 -0
  72. package/build/contracts/vault/DonationVault.sol/DonationVault.json +108 -0
  73. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  74. package/build/contracts/vault/IVault.sol/IVault.json +5 -0
  75. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  76. package/build/contracts/vault/TBTCVault.sol/TBTCVault.json +273 -5
  77. package/contracts/GovernanceUtils.sol +4 -4
  78. package/contracts/bank/Bank.sol +113 -66
  79. package/contracts/bank/IReceiveBalanceApproval.sol +45 -0
  80. package/contracts/bridge/BitcoinTx.sol +267 -10
  81. package/contracts/bridge/Bridge.sol +1698 -245
  82. package/contracts/bridge/BridgeState.sol +768 -0
  83. package/contracts/bridge/Deposit.sol +269 -0
  84. package/contracts/bridge/DepositSweep.sol +574 -0
  85. package/contracts/bridge/EcdsaLib.sol +45 -0
  86. package/contracts/bridge/Fraud.sol +579 -0
  87. package/contracts/bridge/Heartbeat.sol +112 -0
  88. package/contracts/bridge/IRelay.sol +28 -0
  89. package/contracts/bridge/MovingFunds.sol +1077 -0
  90. package/contracts/bridge/Redemption.sol +1058 -0
  91. package/contracts/bridge/VendingMachine.sol +2 -2
  92. package/contracts/bridge/Wallets.sol +719 -0
  93. package/contracts/hardhat-dependency-compiler/.hardhat-dependency-compiler +1 -0
  94. package/contracts/hardhat-dependency-compiler/@keep-network/ecdsa/contracts/WalletRegistry.sol +3 -0
  95. package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol +3 -0
  96. package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol +3 -0
  97. package/contracts/token/TBTC.sol +1 -1
  98. package/contracts/vault/DonationVault.sol +125 -0
  99. package/contracts/vault/IVault.sol +6 -22
  100. package/contracts/vault/TBTCVault.sol +188 -29
  101. package/deploy/00_resolve_relay.ts +28 -0
  102. package/deploy/{03_transfer_roles.ts → 03_transfer_vending_machine_roles.ts} +1 -1
  103. package/deploy/04_deploy_bank.ts +27 -0
  104. package/deploy/05_deploy_bridge.ts +80 -0
  105. package/deploy/06_deploy_tbtc_vault.ts +30 -0
  106. package/deploy/07_bank_update_bridge.ts +19 -0
  107. package/deploy/08_transfer_bank_ownership.ts +15 -0
  108. package/deploy/09_transfer_tbtc_vault_ownership.ts +15 -0
  109. package/deploy/10_transfer_bridge_governance.ts +20 -0
  110. package/deploy/11_initialize_wallet_owner.ts +18 -0
  111. package/deploy/11_transfer_proxy_admin_ownership.ts +30 -0
  112. package/deploy/12_deploy_proxy_admin_with_deputy.ts +33 -0
  113. package/export.json +15771 -443
  114. package/package.json +34 -26
  115. package/artifacts/solcInputs/524094faac10a04084fcc411e06dab84.json +0 -128
@@ -0,0 +1,768 @@
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 {IWalletRegistry as EcdsaWalletRegistry} from "@keep-network/ecdsa/contracts/api/IWalletRegistry.sol";
19
+
20
+ import "./IRelay.sol";
21
+ import "./Deposit.sol";
22
+ import "./Redemption.sol";
23
+ import "./Fraud.sol";
24
+ import "./Wallets.sol";
25
+ import "./MovingFunds.sol";
26
+
27
+ import "../bank/Bank.sol";
28
+
29
+ library BridgeState {
30
+ struct Storage {
31
+ // Address of the Bank the Bridge belongs to.
32
+ Bank bank;
33
+ // Bitcoin relay providing the current Bitcoin network difficulty.
34
+ IRelay relay;
35
+ // The number of confirmations on the Bitcoin chain required to
36
+ // successfully evaluate an SPV proof.
37
+ uint96 txProofDifficultyFactor;
38
+ // ECDSA Wallet Registry contract handle.
39
+ EcdsaWalletRegistry ecdsaWalletRegistry;
40
+ // Address where the deposit and redemption treasury fees will be sent
41
+ // to. Treasury takes part in the operators rewarding process.
42
+ address treasury;
43
+ // Move depositDustThreshold to the next storage slot for a more
44
+ // efficient variable layout in the storage.
45
+ // slither-disable-next-line unused-state
46
+ bytes32 __treasuryAlignmentGap;
47
+ // The minimal amount that can be requested to deposit.
48
+ // Value of this parameter must take into account the value of
49
+ // `depositTreasuryFeeDivisor` and `depositTxMaxFee` parameters in order
50
+ // to make requests that can incur the treasury and transaction fee and
51
+ // still satisfy the depositor.
52
+ uint64 depositDustThreshold;
53
+ // Divisor used to compute the treasury fee taken from each deposit and
54
+ // transferred to the treasury upon sweep proof submission. That fee is
55
+ // computed as follows:
56
+ // `treasuryFee = depositedAmount / depositTreasuryFeeDivisor`
57
+ // For example, if the treasury fee needs to be 2% of each deposit,
58
+ // the `depositTreasuryFeeDivisor` should be set to `50` because
59
+ // `1/50 = 0.02 = 2%`.
60
+ uint64 depositTreasuryFeeDivisor;
61
+ // Maximum amount of BTC transaction fee that can be incurred by each
62
+ // swept deposit being part of the given sweep transaction. If the
63
+ // maximum BTC transaction fee is exceeded, such transaction is
64
+ // considered a fraud.
65
+ //
66
+ // This is a per-deposit input max fee for the sweep transaction.
67
+ uint64 depositTxMaxFee;
68
+ // Move movingFundsTxMaxTotalFee to the next storage slot for a more
69
+ // efficient variable layout in the storage.
70
+ // slither-disable-next-line unused-state
71
+ bytes32 __depositAlignmentGap;
72
+ // Maximum amount of the total BTC transaction fee that is acceptable in
73
+ // a single moving funds transaction.
74
+ //
75
+ // This is a TOTAL max fee for the moving funds transaction. Note
76
+ // that `depositTxMaxFee` is per single deposit and `redemptionTxMaxFee`
77
+ // if per single redemption. `movingFundsTxMaxTotalFee` is a total
78
+ // fee for the entire transaction.
79
+ uint64 movingFundsTxMaxTotalFee;
80
+ // The minimal satoshi amount that makes sense to be transferred during
81
+ // the moving funds process. Moving funds wallets having their BTC
82
+ // balance below that value can begin closing immediately as
83
+ // transferring such a low value may not be possible due to
84
+ // BTC network fees. The value of this parameter must always be lower
85
+ // than `redemptionDustThreshold` in order to prevent redemption requests
86
+ // with values lower or equal to `movingFundsDustThreshold`.
87
+ uint64 movingFundsDustThreshold;
88
+ // Time after which the moving funds timeout can be reset in case the
89
+ // target wallet commitment cannot be submitted due to a lack of live
90
+ // wallets in the system. It is counted from the moment when the wallet
91
+ // was requested to move their funds and switched to the MovingFunds
92
+ // state or from the moment the timeout was reset the last time.
93
+ // Value in seconds. This value should be lower than the value
94
+ // of the `movingFundsTimeout`.
95
+ uint32 movingFundsTimeoutResetDelay;
96
+ // Time after which the moving funds process can be reported as
97
+ // timed out. It is counted from the moment when the wallet
98
+ // was requested to move their funds and switched to the MovingFunds
99
+ // state. Value in seconds.
100
+ uint32 movingFundsTimeout;
101
+ // The amount of stake slashed from each member of a wallet for a moving
102
+ // funds timeout.
103
+ uint96 movingFundsTimeoutSlashingAmount;
104
+ // The percentage of the notifier reward from the staking contract
105
+ // the notifier of a moving funds timeout receives. The value is in the
106
+ // range [0, 100].
107
+ uint32 movingFundsTimeoutNotifierRewardMultiplier;
108
+ // Move movedFundsSweepTxMaxTotalFee to the next storage slot for a more
109
+ // efficient variable layout in the storage.
110
+ // slither-disable-next-line unused-state
111
+ bytes32 __movingFundsAlignmentGap;
112
+ // Maximum amount of the total BTC transaction fee that is acceptable in
113
+ // a single moved funds sweep transaction.
114
+ //
115
+ // This is a TOTAL max fee for the moved funds sweep transaction. Note
116
+ // that `depositTxMaxFee` is per single deposit and `redemptionTxMaxFee`
117
+ // if per single redemption. `movedFundsSweepTxMaxTotalFee` is a total
118
+ // fee for the entire transaction.
119
+ uint64 movedFundsSweepTxMaxTotalFee;
120
+ // Time after which the moved funds sweep process can be reported as
121
+ // timed out. It is counted from the moment when the recipient wallet
122
+ // was requested to sweep the received funds. Value in seconds.
123
+ uint32 movedFundsSweepTimeout;
124
+ // The amount of stake slashed from each member of a wallet for a moved
125
+ // funds sweep timeout.
126
+ uint96 movedFundsSweepTimeoutSlashingAmount;
127
+ // The percentage of the notifier reward from the staking contract
128
+ // the notifier of a moved funds sweep timeout receives. The value is
129
+ // in the range [0, 100].
130
+ uint32 movedFundsSweepTimeoutNotifierRewardMultiplier;
131
+ // The minimal amount that can be requested for redemption.
132
+ // Value of this parameter must take into account the value of
133
+ // `redemptionTreasuryFeeDivisor` and `redemptionTxMaxFee`
134
+ // parameters in order to make requests that can incur the
135
+ // treasury and transaction fee and still satisfy the redeemer.
136
+ // Additionally, the value of this parameter must always be greater
137
+ // than `movingFundsDustThreshold` in order to prevent redemption
138
+ // requests with values lower or equal to `movingFundsDustThreshold`.
139
+ uint64 redemptionDustThreshold;
140
+ // Divisor used to compute the treasury fee taken from each
141
+ // redemption request and transferred to the treasury upon
142
+ // successful request finalization. That fee is computed as follows:
143
+ // `treasuryFee = requestedAmount / redemptionTreasuryFeeDivisor`
144
+ // For example, if the treasury fee needs to be 2% of each
145
+ // redemption request, the `redemptionTreasuryFeeDivisor` should
146
+ // be set to `50` because `1/50 = 0.02 = 2%`.
147
+ uint64 redemptionTreasuryFeeDivisor;
148
+ // Maximum amount of BTC transaction fee that can be incurred by
149
+ // each redemption request being part of the given redemption
150
+ // transaction. If the maximum BTC transaction fee is exceeded, such
151
+ // transaction is considered a fraud.
152
+ //
153
+ // This is a per-redemption output max fee for the redemption
154
+ // transaction.
155
+ uint64 redemptionTxMaxFee;
156
+ // Move redemptionTimeout to the next storage slot for a more efficient
157
+ // variable layout in the storage.
158
+ // slither-disable-next-line unused-state
159
+ bytes32 __redemptionAlignmentGap;
160
+ // Time after which the redemption request can be reported as
161
+ // timed out. It is counted from the moment when the redemption
162
+ // request was created via `requestRedemption` call. Reported
163
+ // timed out requests are cancelled and locked TBTC is returned
164
+ // to the redeemer in full amount.
165
+ uint32 redemptionTimeout;
166
+ // The amount of stake slashed from each member of a wallet for a
167
+ // redemption timeout.
168
+ uint96 redemptionTimeoutSlashingAmount;
169
+ // The percentage of the notifier reward from the staking contract
170
+ // the notifier of a redemption timeout receives. The value is in the
171
+ // range [0, 100].
172
+ uint32 redemptionTimeoutNotifierRewardMultiplier;
173
+ // The amount of ETH in wei the party challenging the wallet for fraud
174
+ // needs to deposit.
175
+ uint96 fraudChallengeDepositAmount;
176
+ // The amount of time the wallet has to defeat a fraud challenge.
177
+ uint32 fraudChallengeDefeatTimeout;
178
+ // The amount of stake slashed from each member of a wallet for a fraud.
179
+ uint96 fraudSlashingAmount;
180
+ // The percentage of the notifier reward from the staking contract
181
+ // the notifier of a fraud receives. The value is in the range [0, 100].
182
+ uint32 fraudNotifierRewardMultiplier;
183
+ // Determines how frequently a new wallet creation can be requested.
184
+ // Value in seconds.
185
+ uint32 walletCreationPeriod;
186
+ // The minimum BTC threshold in satoshi that is used to decide about
187
+ // wallet creation. Specifically, we allow for the creation of a new
188
+ // wallet if the active wallet is old enough and their amount of BTC
189
+ // is greater than or equal this threshold.
190
+ uint64 walletCreationMinBtcBalance;
191
+ // The maximum BTC threshold in satoshi that is used to decide about
192
+ // wallet creation. Specifically, we allow for the creation of a new
193
+ // wallet if the active wallet's amount of BTC is greater than or equal
194
+ // this threshold, regardless of the active wallet's age.
195
+ uint64 walletCreationMaxBtcBalance;
196
+ // The minimum BTC threshold in satoshi that is used to decide about
197
+ // wallet closing. Specifically, we allow for the closure of the given
198
+ // wallet if their amount of BTC is lesser than this threshold,
199
+ // regardless of the wallet's age.
200
+ uint64 walletClosureMinBtcBalance;
201
+ // The maximum age of a wallet in seconds, after which the wallet
202
+ // moving funds process can be requested.
203
+ uint32 walletMaxAge;
204
+ // 20-byte wallet public key hash being reference to the currently
205
+ // active wallet. Can be unset to the zero value under certain
206
+ // circumstances.
207
+ bytes20 activeWalletPubKeyHash;
208
+ // The current number of wallets in the Live state.
209
+ uint32 liveWalletsCount;
210
+ // The maximum BTC amount in satoshi than can be transferred to a single
211
+ // target wallet during the moving funds process.
212
+ uint64 walletMaxBtcTransfer;
213
+ // Determines the length of the wallet closing period, i.e. the period
214
+ // when the wallet remains in the Closing state and can be subject
215
+ // of deposit fraud challenges. This value is in seconds and should be
216
+ // greater than the deposit refund time plus some time margin.
217
+ uint32 walletClosingPeriod;
218
+ // Collection of all revealed deposits indexed by
219
+ // `keccak256(fundingTxHash | fundingOutputIndex)`.
220
+ // The `fundingTxHash` is `bytes32` (ordered as in Bitcoin internally)
221
+ // and `fundingOutputIndex` an `uint32`. This mapping may contain valid
222
+ // and invalid deposits and the wallet is responsible for validating
223
+ // them before attempting to execute a sweep.
224
+ mapping(uint256 => Deposit.DepositRequest) deposits;
225
+ // Indicates if the vault with the given address is trusted or not.
226
+ // Depositors can route their revealed deposits only to trusted vaults
227
+ // and have trusted vaults notified about new deposits as soon as these
228
+ // deposits get swept. Vaults not trusted by the Bridge can still be
229
+ // used by Bank balance owners on their own responsibility - anyone can
230
+ // approve their Bank balance to any address.
231
+ mapping(address => bool) isVaultTrusted;
232
+ // Collection of all moved funds sweep requests indexed by
233
+ // `keccak256(movingFundsTxHash | movingFundsOutputIndex)`.
234
+ // The `movingFundsTxHash` is `bytes32` (ordered as in Bitcoin
235
+ // internally) and `movingFundsOutputIndex` an `uint32`. Each entry
236
+ // is actually an UTXO representing the moved funds and is supposed
237
+ // to be swept with the current main UTXO of the recipient wallet.
238
+ mapping(uint256 => MovingFunds.MovedFundsSweepRequest) movedFundsSweepRequests;
239
+ // Collection of all pending redemption requests indexed by
240
+ // redemption key built as
241
+ // `keccak256(keccak256(redeemerOutputScript) | walletPubKeyHash)`.
242
+ // The `walletPubKeyHash` is the 20-byte wallet's public key hash
243
+ // (computed using Bitcoin HASH160 over the compressed ECDSA
244
+ // public key) and `redeemerOutputScript` is a Bitcoin script
245
+ // (P2PKH, P2WPKH, P2SH or P2WSH) that will be used to lock
246
+ // redeemed BTC as requested by the redeemer. Requests are added
247
+ // to this mapping by the `requestRedemption` method (duplicates
248
+ // not allowed) and are removed by one of the following methods:
249
+ // - `submitRedemptionProof` in case the request was handled
250
+ // successfully,
251
+ // - `notifyRedemptionTimeout` in case the request was reported
252
+ // to be timed out.
253
+ mapping(uint256 => Redemption.RedemptionRequest) pendingRedemptions;
254
+ // Collection of all timed out redemptions requests indexed by
255
+ // redemption key built as
256
+ // `keccak256(keccak256(redeemerOutputScript) | walletPubKeyHash)`.
257
+ // The `walletPubKeyHash` is the 20-byte wallet's public key hash
258
+ // (computed using Bitcoin HASH160 over the compressed ECDSA
259
+ // public key) and `redeemerOutputScript` is the Bitcoin script
260
+ // (P2PKH, P2WPKH, P2SH or P2WSH) that is involved in the timed
261
+ // out request. Timed out requests are stored in this mapping to
262
+ // avoid slashing the wallets multiple times for the same timeout.
263
+ // Only one method can add to this mapping:
264
+ // - `notifyRedemptionTimeout` which puts the redemption key to this
265
+ // mapping basing on a timed out request stored previously in
266
+ // `pendingRedemptions` mapping.
267
+ mapping(uint256 => Redemption.RedemptionRequest) timedOutRedemptions;
268
+ // Collection of all submitted fraud challenges indexed by challenge
269
+ // key built as `keccak256(walletPublicKey|sighash)`.
270
+ mapping(uint256 => Fraud.FraudChallenge) fraudChallenges;
271
+ // Collection of main UTXOs that are honestly spent indexed by
272
+ // `keccak256(fundingTxHash | fundingOutputIndex)`. The `fundingTxHash`
273
+ // is `bytes32` (ordered as in Bitcoin internally) and
274
+ // `fundingOutputIndex` an `uint32`. A main UTXO is considered honestly
275
+ // spent if it was used as an input of a transaction that have been
276
+ // proven in the Bridge.
277
+ mapping(uint256 => bool) spentMainUTXOs;
278
+ // Maps the 20-byte wallet public key hash (computed using Bitcoin
279
+ // HASH160 over the compressed ECDSA public key) to the basic wallet
280
+ // information like state and pending redemptions value.
281
+ mapping(bytes20 => Wallets.Wallet) registeredWallets;
282
+ // Reserved storage space in case we need to add more variables.
283
+ // The convention from OpenZeppelin suggests the storage space should
284
+ // add up to 50 slots. Here we want to have more slots as there are
285
+ // planned upgrades of the Bridge contract. If more entires are added to
286
+ // the struct in the upcoming versions we need to reduce the array size.
287
+ // See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
288
+ // slither-disable-next-line unused-state
289
+ uint256[50] __gap;
290
+ }
291
+
292
+ event DepositParametersUpdated(
293
+ uint64 depositDustThreshold,
294
+ uint64 depositTreasuryFeeDivisor,
295
+ uint64 depositTxMaxFee
296
+ );
297
+
298
+ event RedemptionParametersUpdated(
299
+ uint64 redemptionDustThreshold,
300
+ uint64 redemptionTreasuryFeeDivisor,
301
+ uint64 redemptionTxMaxFee,
302
+ uint32 redemptionTimeout,
303
+ uint96 redemptionTimeoutSlashingAmount,
304
+ uint32 redemptionTimeoutNotifierRewardMultiplier
305
+ );
306
+
307
+ event MovingFundsParametersUpdated(
308
+ uint64 movingFundsTxMaxTotalFee,
309
+ uint64 movingFundsDustThreshold,
310
+ uint32 movingFundsTimeoutResetDelay,
311
+ uint32 movingFundsTimeout,
312
+ uint96 movingFundsTimeoutSlashingAmount,
313
+ uint32 movingFundsTimeoutNotifierRewardMultiplier,
314
+ uint64 movedFundsSweepTxMaxTotalFee,
315
+ uint32 movedFundsSweepTimeout,
316
+ uint96 movedFundsSweepTimeoutSlashingAmount,
317
+ uint32 movedFundsSweepTimeoutNotifierRewardMultiplier
318
+ );
319
+
320
+ event WalletParametersUpdated(
321
+ uint32 walletCreationPeriod,
322
+ uint64 walletCreationMinBtcBalance,
323
+ uint64 walletCreationMaxBtcBalance,
324
+ uint64 walletClosureMinBtcBalance,
325
+ uint32 walletMaxAge,
326
+ uint64 walletMaxBtcTransfer,
327
+ uint32 walletClosingPeriod
328
+ );
329
+
330
+ event FraudParametersUpdated(
331
+ uint96 fraudChallengeDepositAmount,
332
+ uint32 fraudChallengeDefeatTimeout,
333
+ uint96 fraudSlashingAmount,
334
+ uint32 fraudNotifierRewardMultiplier
335
+ );
336
+
337
+ /// @notice Updates parameters of deposits.
338
+ /// @param _depositDustThreshold New value of the deposit dust threshold in
339
+ /// satoshis. It is the minimal amount that can be requested to
340
+ //// deposit. Value of this parameter must take into account the value
341
+ /// of `depositTreasuryFeeDivisor` and `depositTxMaxFee` parameters
342
+ /// in order to make requests that can incur the treasury and
343
+ /// transaction fee and still satisfy the depositor.
344
+ /// @param _depositTreasuryFeeDivisor New value of the treasury fee divisor.
345
+ /// It is the divisor used to compute the treasury fee taken from
346
+ /// each deposit and transferred to the treasury upon sweep proof
347
+ /// submission. That fee is computed as follows:
348
+ /// `treasuryFee = depositedAmount / depositTreasuryFeeDivisor`
349
+ /// For example, if the treasury fee needs to be 2% of each deposit,
350
+ /// the `depositTreasuryFeeDivisor` should be set to `50`
351
+ /// because `1/50 = 0.02 = 2%`.
352
+ /// @param _depositTxMaxFee New value of the deposit tx max fee in satoshis.
353
+ /// It is the maximum amount of BTC transaction fee that can
354
+ /// be incurred by each swept deposit being part of the given sweep
355
+ /// transaction. If the maximum BTC transaction fee is exceeded,
356
+ /// such transaction is considered a fraud.
357
+ /// @dev Requirements:
358
+ /// - Deposit dust threshold must be greater than zero,
359
+ /// - Deposit dust threshold must be greater than deposit TX max fee,
360
+ /// - Deposit treasury fee divisor must be greater than zero,
361
+ /// - Deposit transaction max fee must be greater than zero.
362
+ function updateDepositParameters(
363
+ Storage storage self,
364
+ uint64 _depositDustThreshold,
365
+ uint64 _depositTreasuryFeeDivisor,
366
+ uint64 _depositTxMaxFee
367
+ ) internal {
368
+ require(
369
+ _depositDustThreshold > 0,
370
+ "Deposit dust threshold must be greater than zero"
371
+ );
372
+
373
+ require(
374
+ _depositDustThreshold > _depositTxMaxFee,
375
+ "Deposit dust threshold must be greater than deposit TX max fee"
376
+ );
377
+
378
+ require(
379
+ _depositTreasuryFeeDivisor > 0,
380
+ "Deposit treasury fee divisor must be greater than zero"
381
+ );
382
+
383
+ require(
384
+ _depositTxMaxFee > 0,
385
+ "Deposit transaction max fee must be greater than zero"
386
+ );
387
+
388
+ self.depositDustThreshold = _depositDustThreshold;
389
+ self.depositTreasuryFeeDivisor = _depositTreasuryFeeDivisor;
390
+ self.depositTxMaxFee = _depositTxMaxFee;
391
+
392
+ emit DepositParametersUpdated(
393
+ _depositDustThreshold,
394
+ _depositTreasuryFeeDivisor,
395
+ _depositTxMaxFee
396
+ );
397
+ }
398
+
399
+ /// @notice Updates parameters of redemptions.
400
+ /// @param _redemptionDustThreshold New value of the redemption dust
401
+ /// threshold in satoshis. It is the minimal amount that can be
402
+ /// requested for redemption. Value of this parameter must take into
403
+ /// account the value of `redemptionTreasuryFeeDivisor` and
404
+ /// `redemptionTxMaxFee` parameters in order to make requests that
405
+ /// can incur the treasury and transaction fee and still satisfy the
406
+ /// redeemer.
407
+ /// @param _redemptionTreasuryFeeDivisor New value of the redemption
408
+ /// treasury fee divisor. It is the divisor used to compute the
409
+ /// treasury fee taken from each redemption request and transferred
410
+ /// to the treasury upon successful request finalization. That fee is
411
+ /// computed as follows:
412
+ /// `treasuryFee = requestedAmount / redemptionTreasuryFeeDivisor`
413
+ /// For example, if the treasury fee needs to be 2% of each
414
+ /// redemption request, the `redemptionTreasuryFeeDivisor` should
415
+ /// be set to `50` because `1/50 = 0.02 = 2%`.
416
+ /// @param _redemptionTxMaxFee New value of the redemption transaction max
417
+ /// fee in satoshis. It is the maximum amount of BTC transaction fee
418
+ /// that can be incurred by each redemption request being part of the
419
+ /// given redemption transaction. If the maximum BTC transaction fee
420
+ /// is exceeded, such transaction is considered a fraud.
421
+ /// This is a per-redemption output max fee for the redemption
422
+ /// transaction.
423
+ /// @param _redemptionTimeout New value of the redemption timeout in seconds.
424
+ /// It is the time after which the redemption request can be reported
425
+ /// as timed out. It is counted from the moment when the redemption
426
+ /// request was created via `requestRedemption` call. Reported timed
427
+ /// out requests are cancelled and locked TBTC is returned to the
428
+ /// redeemer in full amount.
429
+ /// @param _redemptionTimeoutSlashingAmount New value of the redemption
430
+ /// timeout slashing amount in T, it is the amount slashed from each
431
+ /// wallet member for redemption timeout.
432
+ /// @param _redemptionTimeoutNotifierRewardMultiplier New value of the
433
+ /// redemption timeout notifier reward multiplier as percentage,
434
+ /// it determines the percentage of the notifier reward from the
435
+ /// staking contact the notifier of a redemption timeout receives.
436
+ /// The value must be in the range [0, 100].
437
+ /// @dev Requirements:
438
+ /// - Redemption dust threshold must be greater than moving funds dust
439
+ /// threshold,
440
+ /// - Redemption dust threshold must be greater than the redemption TX
441
+ /// max fee,
442
+ /// - Redemption treasury fee divisor must be greater than zero,
443
+ /// - Redemption transaction max fee must be greater than zero,
444
+ /// - Redemption timeout must be greater than zero,
445
+ /// - Redemption timeout notifier reward multiplier must be in the
446
+ /// range [0, 100].
447
+ function updateRedemptionParameters(
448
+ Storage storage self,
449
+ uint64 _redemptionDustThreshold,
450
+ uint64 _redemptionTreasuryFeeDivisor,
451
+ uint64 _redemptionTxMaxFee,
452
+ uint32 _redemptionTimeout,
453
+ uint96 _redemptionTimeoutSlashingAmount,
454
+ uint32 _redemptionTimeoutNotifierRewardMultiplier
455
+ ) internal {
456
+ require(
457
+ _redemptionDustThreshold > self.movingFundsDustThreshold,
458
+ "Redemption dust threshold must be greater than moving funds dust threshold"
459
+ );
460
+
461
+ require(
462
+ _redemptionDustThreshold > _redemptionTxMaxFee,
463
+ "Redemption dust threshold must be greater than redemption TX max fee"
464
+ );
465
+
466
+ require(
467
+ _redemptionTreasuryFeeDivisor > 0,
468
+ "Redemption treasury fee divisor must be greater than zero"
469
+ );
470
+
471
+ require(
472
+ _redemptionTxMaxFee > 0,
473
+ "Redemption transaction max fee must be greater than zero"
474
+ );
475
+
476
+ require(
477
+ _redemptionTimeout > 0,
478
+ "Redemption timeout must be greater than zero"
479
+ );
480
+
481
+ require(
482
+ _redemptionTimeoutNotifierRewardMultiplier <= 100,
483
+ "Redemption timeout notifier reward multiplier must be in the range [0, 100]"
484
+ );
485
+
486
+ self.redemptionDustThreshold = _redemptionDustThreshold;
487
+ self.redemptionTreasuryFeeDivisor = _redemptionTreasuryFeeDivisor;
488
+ self.redemptionTxMaxFee = _redemptionTxMaxFee;
489
+ self.redemptionTimeout = _redemptionTimeout;
490
+ self.redemptionTimeoutSlashingAmount = _redemptionTimeoutSlashingAmount;
491
+ self
492
+ .redemptionTimeoutNotifierRewardMultiplier = _redemptionTimeoutNotifierRewardMultiplier;
493
+
494
+ emit RedemptionParametersUpdated(
495
+ _redemptionDustThreshold,
496
+ _redemptionTreasuryFeeDivisor,
497
+ _redemptionTxMaxFee,
498
+ _redemptionTimeout,
499
+ _redemptionTimeoutSlashingAmount,
500
+ _redemptionTimeoutNotifierRewardMultiplier
501
+ );
502
+ }
503
+
504
+ /// @notice Updates parameters of moving funds.
505
+ /// @param _movingFundsTxMaxTotalFee New value of the moving funds transaction
506
+ /// max total fee in satoshis. It is the maximum amount of the total
507
+ /// BTC transaction fee that is acceptable in a single moving funds
508
+ /// transaction. This is a _total_ max fee for the entire moving
509
+ /// funds transaction.
510
+ /// @param _movingFundsDustThreshold New value of the moving funds dust
511
+ /// threshold. It is the minimal satoshi amount that makes sense to
512
+ /// be transferred during the moving funds process. Moving funds
513
+ /// wallets having their BTC balance below that value can begin
514
+ /// closing immediately as transferring such a low value may not be
515
+ /// possible due to BTC network fees.
516
+ /// @param _movingFundsTimeoutResetDelay New value of the moving funds
517
+ /// timeout reset delay in seconds. It is the time after which the
518
+ /// moving funds timeout can be reset in case the target wallet
519
+ /// commitment cannot be submitted due to a lack of live wallets
520
+ /// in the system. It is counted from the moment when the wallet
521
+ /// was requested to move their funds and switched to the MovingFunds
522
+ /// state or from the moment the timeout was reset the last time.
523
+ /// @param _movingFundsTimeout New value of the moving funds timeout in
524
+ /// seconds. It is the time after which the moving funds process can
525
+ /// be reported as timed out. It is counted from the moment when the
526
+ /// wallet was requested to move their funds and switched to the
527
+ /// MovingFunds state.
528
+ /// @param _movingFundsTimeoutSlashingAmount New value of the moving funds
529
+ /// timeout slashing amount in T, it is the amount slashed from each
530
+ /// wallet member for moving funds timeout.
531
+ /// @param _movingFundsTimeoutNotifierRewardMultiplier New value of the
532
+ /// moving funds timeout notifier reward multiplier as percentage,
533
+ /// it determines the percentage of the notifier reward from the
534
+ /// staking contact the notifier of a moving funds timeout receives.
535
+ /// The value must be in the range [0, 100].
536
+ /// @param _movedFundsSweepTxMaxTotalFee New value of the moved funds sweep
537
+ /// transaction max total fee in satoshis. It is the maximum amount
538
+ /// of the total BTC transaction fee that is acceptable in a single
539
+ /// moved funds sweep transaction. This is a _total_ max fee for the
540
+ /// entire moved funds sweep transaction.
541
+ /// @param _movedFundsSweepTimeout New value of the moved funds sweep
542
+ /// timeout in seconds. It is the time after which the moved funds
543
+ /// sweep process can be reported as timed out. It is counted from
544
+ /// the moment when the wallet was requested to sweep the received
545
+ /// funds.
546
+ /// @param _movedFundsSweepTimeoutSlashingAmount New value of the moved
547
+ /// funds sweep timeout slashing amount in T, it is the amount
548
+ /// slashed from each wallet member for moved funds sweep timeout.
549
+ /// @param _movedFundsSweepTimeoutNotifierRewardMultiplier New value of
550
+ /// the moved funds sweep timeout notifier reward multiplier as
551
+ /// percentage, it determines the percentage of the notifier reward
552
+ /// from the staking contact the notifier of a moved funds sweep
553
+ /// timeout receives. The value must be in the range [0, 100].
554
+ /// @dev Requirements:
555
+ /// - Moving funds transaction max total fee must be greater than zero,
556
+ /// - Moving funds dust threshold must be greater than zero and lower
557
+ /// than the redemption dust threshold,
558
+ /// - Moving funds timeout reset delay must be greater than zero,
559
+ /// - Moving funds timeout must be greater than the moving funds
560
+ /// timeout reset delay,
561
+ /// - Moving funds timeout notifier reward multiplier must be in the
562
+ /// range [0, 100],
563
+ /// - Moved funds sweep transaction max total fee must be greater than zero,
564
+ /// - Moved funds sweep timeout must be greater than zero,
565
+ /// - Moved funds sweep timeout notifier reward multiplier must be in the
566
+ /// range [0, 100].
567
+ function updateMovingFundsParameters(
568
+ Storage storage self,
569
+ uint64 _movingFundsTxMaxTotalFee,
570
+ uint64 _movingFundsDustThreshold,
571
+ uint32 _movingFundsTimeoutResetDelay,
572
+ uint32 _movingFundsTimeout,
573
+ uint96 _movingFundsTimeoutSlashingAmount,
574
+ uint32 _movingFundsTimeoutNotifierRewardMultiplier,
575
+ uint64 _movedFundsSweepTxMaxTotalFee,
576
+ uint32 _movedFundsSweepTimeout,
577
+ uint96 _movedFundsSweepTimeoutSlashingAmount,
578
+ uint32 _movedFundsSweepTimeoutNotifierRewardMultiplier
579
+ ) internal {
580
+ require(
581
+ _movingFundsTxMaxTotalFee > 0,
582
+ "Moving funds transaction max total fee must be greater than zero"
583
+ );
584
+
585
+ require(
586
+ _movingFundsDustThreshold > 0 &&
587
+ _movingFundsDustThreshold < self.redemptionDustThreshold,
588
+ "Moving funds dust threshold must be greater than zero and lower than redemption dust threshold"
589
+ );
590
+
591
+ require(
592
+ _movingFundsTimeoutResetDelay > 0,
593
+ "Moving funds timeout reset delay must be greater than zero"
594
+ );
595
+
596
+ require(
597
+ _movingFundsTimeout > _movingFundsTimeoutResetDelay,
598
+ "Moving funds timeout must be greater than its reset delay"
599
+ );
600
+
601
+ require(
602
+ _movingFundsTimeoutNotifierRewardMultiplier <= 100,
603
+ "Moving funds timeout notifier reward multiplier must be in the range [0, 100]"
604
+ );
605
+
606
+ require(
607
+ _movedFundsSweepTxMaxTotalFee > 0,
608
+ "Moved funds sweep transaction max total fee must be greater than zero"
609
+ );
610
+
611
+ require(
612
+ _movedFundsSweepTimeout > 0,
613
+ "Moved funds sweep timeout must be greater than zero"
614
+ );
615
+
616
+ require(
617
+ _movedFundsSweepTimeoutNotifierRewardMultiplier <= 100,
618
+ "Moved funds sweep timeout notifier reward multiplier must be in the range [0, 100]"
619
+ );
620
+
621
+ self.movingFundsTxMaxTotalFee = _movingFundsTxMaxTotalFee;
622
+ self.movingFundsDustThreshold = _movingFundsDustThreshold;
623
+ self.movingFundsTimeoutResetDelay = _movingFundsTimeoutResetDelay;
624
+ self.movingFundsTimeout = _movingFundsTimeout;
625
+ self
626
+ .movingFundsTimeoutSlashingAmount = _movingFundsTimeoutSlashingAmount;
627
+ self
628
+ .movingFundsTimeoutNotifierRewardMultiplier = _movingFundsTimeoutNotifierRewardMultiplier;
629
+ self.movedFundsSweepTxMaxTotalFee = _movedFundsSweepTxMaxTotalFee;
630
+ self.movedFundsSweepTimeout = _movedFundsSweepTimeout;
631
+ self
632
+ .movedFundsSweepTimeoutSlashingAmount = _movedFundsSweepTimeoutSlashingAmount;
633
+ self
634
+ .movedFundsSweepTimeoutNotifierRewardMultiplier = _movedFundsSweepTimeoutNotifierRewardMultiplier;
635
+
636
+ emit MovingFundsParametersUpdated(
637
+ _movingFundsTxMaxTotalFee,
638
+ _movingFundsDustThreshold,
639
+ _movingFundsTimeoutResetDelay,
640
+ _movingFundsTimeout,
641
+ _movingFundsTimeoutSlashingAmount,
642
+ _movingFundsTimeoutNotifierRewardMultiplier,
643
+ _movedFundsSweepTxMaxTotalFee,
644
+ _movedFundsSweepTimeout,
645
+ _movedFundsSweepTimeoutSlashingAmount,
646
+ _movedFundsSweepTimeoutNotifierRewardMultiplier
647
+ );
648
+ }
649
+
650
+ /// @notice Updates parameters of wallets.
651
+ /// @param _walletCreationPeriod New value of the wallet creation period in
652
+ /// seconds, determines how frequently a new wallet creation can be
653
+ /// requested.
654
+ /// @param _walletCreationMinBtcBalance New value of the wallet minimum BTC
655
+ /// balance in satoshi, used to decide about wallet creation.
656
+ /// @param _walletCreationMaxBtcBalance New value of the wallet maximum BTC
657
+ /// balance in satoshi, used to decide about wallet creation.
658
+ /// @param _walletClosureMinBtcBalance New value of the wallet minimum BTC
659
+ /// balance in satoshi, used to decide about wallet closure.
660
+ /// @param _walletMaxAge New value of the wallet maximum age in seconds,
661
+ /// indicates the maximum age of a wallet in seconds, after which
662
+ /// the wallet moving funds process can be requested.
663
+ /// @param _walletMaxBtcTransfer New value of the wallet maximum BTC transfer
664
+ /// in satoshi, determines the maximum amount that can be transferred
665
+ /// to a single target wallet during the moving funds process.
666
+ /// @param _walletClosingPeriod New value of the wallet closing period in
667
+ /// seconds, determines the length of the wallet closing period,
668
+ // i.e. the period when the wallet remains in the Closing state
669
+ // and can be subject of deposit fraud challenges.
670
+ /// @dev Requirements:
671
+ /// - Wallet minimum BTC balance must be greater than zero,
672
+ /// - Wallet maximum BTC balance must be greater than the wallet
673
+ /// minimum BTC balance,
674
+ /// - Wallet maximum BTC transfer must be greater than zero,
675
+ /// - Wallet closing period must be greater than zero.
676
+ function updateWalletParameters(
677
+ Storage storage self,
678
+ uint32 _walletCreationPeriod,
679
+ uint64 _walletCreationMinBtcBalance,
680
+ uint64 _walletCreationMaxBtcBalance,
681
+ uint64 _walletClosureMinBtcBalance,
682
+ uint32 _walletMaxAge,
683
+ uint64 _walletMaxBtcTransfer,
684
+ uint32 _walletClosingPeriod
685
+ ) internal {
686
+ require(
687
+ _walletCreationMaxBtcBalance > _walletCreationMinBtcBalance,
688
+ "Wallet creation maximum BTC balance must be greater than the creation minimum BTC balance"
689
+ );
690
+ require(
691
+ _walletClosureMinBtcBalance > 0,
692
+ "Wallet closure minimum BTC balance must be greater than zero"
693
+ );
694
+ require(
695
+ _walletMaxBtcTransfer > 0,
696
+ "Wallet maximum BTC transfer must be greater than zero"
697
+ );
698
+ require(
699
+ _walletClosingPeriod > 0,
700
+ "Wallet closing period must be greater than zero"
701
+ );
702
+
703
+ self.walletCreationPeriod = _walletCreationPeriod;
704
+ self.walletCreationMinBtcBalance = _walletCreationMinBtcBalance;
705
+ self.walletCreationMaxBtcBalance = _walletCreationMaxBtcBalance;
706
+ self.walletClosureMinBtcBalance = _walletClosureMinBtcBalance;
707
+ self.walletMaxAge = _walletMaxAge;
708
+ self.walletMaxBtcTransfer = _walletMaxBtcTransfer;
709
+ self.walletClosingPeriod = _walletClosingPeriod;
710
+
711
+ emit WalletParametersUpdated(
712
+ _walletCreationPeriod,
713
+ _walletCreationMinBtcBalance,
714
+ _walletCreationMaxBtcBalance,
715
+ _walletClosureMinBtcBalance,
716
+ _walletMaxAge,
717
+ _walletMaxBtcTransfer,
718
+ _walletClosingPeriod
719
+ );
720
+ }
721
+
722
+ /// @notice Updates parameters related to frauds.
723
+ /// @param _fraudChallengeDepositAmount New value of the fraud challenge
724
+ /// deposit amount in wei, it is the amount of ETH the party
725
+ /// challenging the wallet for fraud needs to deposit.
726
+ /// @param _fraudChallengeDefeatTimeout New value of the challenge defeat
727
+ /// timeout in seconds, it is the amount of time the wallet has to
728
+ /// defeat a fraud challenge. The value must be greater than zero.
729
+ /// @param _fraudSlashingAmount New value of the fraud slashing amount in T,
730
+ /// it is the amount slashed from each wallet member for committing
731
+ /// a fraud.
732
+ /// @param _fraudNotifierRewardMultiplier New value of the fraud notifier
733
+ /// reward multiplier as percentage, it determines the percentage of
734
+ /// the notifier reward from the staking contact the notifier of
735
+ /// a fraud receives. The value must be in the range [0, 100].
736
+ /// @dev Requirements:
737
+ /// - Fraud challenge defeat timeout must be greater than 0,
738
+ /// - Fraud notifier reward multiplier must be in the range [0, 100].
739
+ function updateFraudParameters(
740
+ Storage storage self,
741
+ uint96 _fraudChallengeDepositAmount,
742
+ uint32 _fraudChallengeDefeatTimeout,
743
+ uint96 _fraudSlashingAmount,
744
+ uint32 _fraudNotifierRewardMultiplier
745
+ ) internal {
746
+ require(
747
+ _fraudChallengeDefeatTimeout > 0,
748
+ "Fraud challenge defeat timeout must be greater than zero"
749
+ );
750
+
751
+ require(
752
+ _fraudNotifierRewardMultiplier <= 100,
753
+ "Fraud notifier reward multiplier must be in the range [0, 100]"
754
+ );
755
+
756
+ self.fraudChallengeDepositAmount = _fraudChallengeDepositAmount;
757
+ self.fraudChallengeDefeatTimeout = _fraudChallengeDefeatTimeout;
758
+ self.fraudSlashingAmount = _fraudSlashingAmount;
759
+ self.fraudNotifierRewardMultiplier = _fraudNotifierRewardMultiplier;
760
+
761
+ emit FraudParametersUpdated(
762
+ _fraudChallengeDepositAmount,
763
+ _fraudChallengeDefeatTimeout,
764
+ _fraudSlashingAmount,
765
+ _fraudNotifierRewardMultiplier
766
+ );
767
+ }
768
+ }