@keep-network/tbtc-v2 0.1.1-dev.60 → 0.1.1-dev.63

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 (71) hide show
  1. package/artifacts/Bank.json +3 -3
  2. package/artifacts/Bridge.json +141 -113
  3. package/artifacts/Deposit.json +7 -7
  4. package/artifacts/DepositSweep.json +7 -7
  5. package/artifacts/EcdsaDkgValidator.json +1 -1
  6. package/artifacts/EcdsaInactivity.json +1 -1
  7. package/artifacts/Fraud.json +20 -10
  8. package/artifacts/KeepRegistry.json +1 -1
  9. package/artifacts/KeepStake.json +2 -2
  10. package/artifacts/KeepToken.json +2 -2
  11. package/artifacts/KeepTokenStaking.json +1 -1
  12. package/artifacts/MovingFunds.json +7 -7
  13. package/artifacts/NuCypherStakingEscrow.json +1 -1
  14. package/artifacts/NuCypherToken.json +2 -2
  15. package/artifacts/RandomBeaconStub.json +1 -1
  16. package/artifacts/Redemption.json +9 -9
  17. package/artifacts/ReimbursementPool.json +2 -2
  18. package/artifacts/Relay.json +9 -9
  19. package/artifacts/SortitionPool.json +2 -2
  20. package/artifacts/T.json +2 -2
  21. package/artifacts/TBTC.json +3 -3
  22. package/artifacts/TBTCToken.json +3 -3
  23. package/artifacts/TokenStaking.json +1 -1
  24. package/artifacts/TokenholderGovernor.json +9 -9
  25. package/artifacts/TokenholderTimelock.json +8 -8
  26. package/artifacts/VendingMachine.json +10 -10
  27. package/artifacts/VendingMachineKeep.json +1 -1
  28. package/artifacts/VendingMachineNuCypher.json +1 -1
  29. package/artifacts/WalletRegistry.json +2 -2
  30. package/artifacts/WalletRegistryGovernance.json +2 -2
  31. package/artifacts/Wallets.json +7 -7
  32. package/artifacts/solcInputs/{59994c0eff9c9c3b454733a65b82146c.json → 888980850d09abe497842d2096dd7e11.json} +13 -4
  33. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  34. package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
  35. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
  36. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +2 -2
  37. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
  38. package/build/contracts/bridge/Bridge.sol/Bridge.json +64 -38
  39. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +1 -1
  40. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +2 -2
  41. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +1 -1
  42. package/build/contracts/bridge/Deposit.sol/Deposit.json +2 -2
  43. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +1 -1
  44. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +2 -2
  45. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +1 -1
  46. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +1 -1
  47. package/build/contracts/bridge/Fraud.sol/Fraud.json +2 -2
  48. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.dbg.json +4 -0
  49. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.json +10 -0
  50. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +1 -1
  51. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +1 -1
  52. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +2 -2
  53. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +1 -1
  54. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +2 -2
  55. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +1 -1
  56. package/build/contracts/bridge/Redemption.sol/Redemption.json +2 -2
  57. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  58. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +1 -1
  59. package/build/contracts/bridge/Wallets.sol/Wallets.json +2 -2
  60. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  61. package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +4 -0
  62. package/build/contracts/vault/DonationVault.sol/DonationVault.json +103 -0
  63. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  64. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  65. package/contracts/bridge/BitcoinTx.sol +18 -3
  66. package/contracts/bridge/Bridge.sol +34 -2
  67. package/contracts/bridge/Fraud.sol +81 -4
  68. package/contracts/bridge/Heartbeat.sol +112 -0
  69. package/contracts/vault/DonationVault.sol +125 -0
  70. package/export.json +18 -0
  71. package/package.json +1 -1
@@ -844,8 +844,8 @@ contract Bridge is Governable, EcdsaWalletOwner {
844
844
  /// to protocol rules. To prevent spurious allegations, the caller
845
845
  /// must deposit ETH that is returned back upon justified fraud
846
846
  /// challenge or confiscated otherwise.
847
- ///@param walletPublicKey The public key of the wallet in the uncompressed
848
- /// and unprefixed format (64 bytes)
847
+ /// @param walletPublicKey The public key of the wallet in the uncompressed
848
+ /// and unprefixed format (64 bytes)
849
849
  /// @param sighash The hash that was used to produce the ECDSA signature
850
850
  /// that is the subject of the fraud claim. This hash is constructed
851
851
  /// by applying double SHA-256 over a serialized subset of the
@@ -905,6 +905,38 @@ contract Bridge is Governable, EcdsaWalletOwner {
905
905
  self.defeatFraudChallenge(walletPublicKey, preimage, witness);
906
906
  }
907
907
 
908
+ /// @notice Allows to defeat a pending fraud challenge against a wallet by
909
+ /// proving the sighash and signature were produced for an off-chain
910
+ /// wallet heartbeat message following a strict format.
911
+ /// In order to defeat the challenge the same `walletPublicKey` and
912
+ /// signature (represented by `r`, `s` and `v`) must be provided as
913
+ /// were used to calculate the sighash during heartbeat message
914
+ /// signing. The fraud challenge defeat attempt will only succeed if
915
+ /// the signed message follows a strict format required for
916
+ /// heartbeat messages. If successfully defeated, the fraud
917
+ /// challenge is marked as resolved and the amount of ether
918
+ /// deposited by the challenger is sent to the treasury.
919
+ /// @param walletPublicKey The public key of the wallet in the uncompressed
920
+ /// and unprefixed format (64 bytes)
921
+ /// @param heartbeatMessage Off-chain heartbeat message meeting the heartbeat
922
+ /// message format requirements which produces sighash used to
923
+ /// generate the ECDSA signature that is the subject of the fraud
924
+ /// claim
925
+ /// @dev Requirements:
926
+ /// - `walletPublicKey` and `sighash` calculated as
927
+ /// `hash256(heartbeatMessage)` must identify an open fraud challenge
928
+ /// - `heartbeatMessage` must follow a strict format of heartbeat
929
+ /// messages
930
+ function defeatFraudChallengeWithHeartbeat(
931
+ bytes calldata walletPublicKey,
932
+ bytes calldata heartbeatMessage
933
+ ) external {
934
+ self.defeatFraudChallengeWithHeartbeat(
935
+ walletPublicKey,
936
+ heartbeatMessage
937
+ );
938
+ }
939
+
908
940
  /// @notice Notifies about defeat timeout for the given fraud challenge.
909
941
  /// Can be called only if there was a fraud challenge identified by
910
942
  /// the provided `walletPublicKey` and `sighash` and it was not
@@ -22,6 +22,7 @@ import {CheckBitcoinSigs} from "@keep-network/bitcoin-spv-sol/contracts/CheckBit
22
22
  import "./BitcoinTx.sol";
23
23
  import "./EcdsaLib.sol";
24
24
  import "./BridgeState.sol";
25
+ import "./Heartbeat.sol";
25
26
  import "./MovingFunds.sol";
26
27
  import "./Wallets.sol";
27
28
 
@@ -38,10 +39,18 @@ import "./Wallets.sol";
38
39
  /// signature must be provided as were used to calculate the sighash during
39
40
  /// the challenge. The wallet provides the preimage which produces sighash
40
41
  /// used to generate the ECDSA signature that is the subject of the fraud
41
- /// claim. The fraud challenge defeat attempt will only succeed if the
42
- /// inputs in the preimage are considered honestly spent by the wallet.
43
- /// Therefore the transaction spending the UTXO must be proven in the
44
- /// Bridge before a challenge defeat is called.
42
+ /// claim.
43
+ ///
44
+ /// The fraud challenge defeat attempt will succeed if the inputs in the
45
+ /// preimage are considered honestly spent by the wallet. Therefore the
46
+ /// transaction spending the UTXO must be proven in the Bridge before
47
+ /// a challenge defeat is called.
48
+ ///
49
+ /// Another option is when a malicious wallet member used a signed heartbeat
50
+ /// message periodically produced by the wallet off-chain to challenge the
51
+ /// wallet for a fraud. Anyone from the wallet can defeat the challenge by
52
+ /// proving the sighash and signature were produced for a heartbeat message
53
+ /// following a strict format.
45
54
  library Fraud {
46
55
  using Wallets for BridgeState.Storage;
47
56
 
@@ -73,6 +82,10 @@ library Fraud {
73
82
 
74
83
  event FraudChallengeDefeatTimedOut(
75
84
  bytes20 walletPubKeyHash,
85
+ // Sighash calculated as a Bitcoin's hash256 (double sha2) of:
86
+ // - a preimage of a transaction spending UTXO according to the protocol
87
+ // rules OR
88
+ // - a valid heartbeat message produced by the wallet off-chain.
76
89
  bytes32 sighash
77
90
  );
78
91
 
@@ -234,6 +247,69 @@ library Fraud {
234
247
  "Spent UTXO not found among correctly spent UTXOs"
235
248
  );
236
249
 
250
+ resolveFraudChallenge(self, walletPublicKey, challenge, sighash);
251
+ }
252
+
253
+ /// @notice Allows to defeat a pending fraud challenge against a wallet by
254
+ /// proving the sighash and signature were produced for an off-chain
255
+ /// wallet heartbeat message following a strict format.
256
+ /// In order to defeat the challenge the same `walletPublicKey` and
257
+ /// signature (represented by `r`, `s` and `v`) must be provided as
258
+ /// were used to calculate the sighash during heartbeat message
259
+ /// signing. The fraud challenge defeat attempt will only succeed if
260
+ /// the signed message follows a strict format required for
261
+ /// heartbeat messages. If successfully defeated, the fraud
262
+ /// challenge is marked as resolved and the amount of ether
263
+ /// deposited by the challenger is sent to the treasury.
264
+ /// @param walletPublicKey The public key of the wallet in the uncompressed
265
+ /// and unprefixed format (64 bytes)
266
+ /// @param heartbeatMessage Off-chain heartbeat message meeting the heartbeat
267
+ /// message format requirements which produces sighash used to
268
+ /// generate the ECDSA signature that is the subject of the fraud
269
+ /// claim
270
+ /// @dev Requirements:
271
+ /// - `walletPublicKey` and `sighash` calculated as
272
+ /// `hash256(heartbeatMessage)` must identify an open fraud challenge
273
+ /// - `heartbeatMessage` must follow a strict format of heartbeat
274
+ /// messages
275
+ function defeatFraudChallengeWithHeartbeat(
276
+ BridgeState.Storage storage self,
277
+ bytes calldata walletPublicKey,
278
+ bytes calldata heartbeatMessage
279
+ ) external {
280
+ bytes32 sighash = heartbeatMessage.hash256();
281
+
282
+ uint256 challengeKey = uint256(
283
+ keccak256(abi.encodePacked(walletPublicKey, sighash))
284
+ );
285
+
286
+ FraudChallenge storage challenge = self.fraudChallenges[challengeKey];
287
+
288
+ require(challenge.reportedAt > 0, "Fraud challenge does not exist");
289
+ require(
290
+ !challenge.resolved,
291
+ "Fraud challenge has already been resolved"
292
+ );
293
+
294
+ require(
295
+ Heartbeat.isValidHeartbeatMessage(heartbeatMessage),
296
+ "Not a valid heartbeat message"
297
+ );
298
+
299
+ resolveFraudChallenge(self, walletPublicKey, challenge, sighash);
300
+ }
301
+
302
+ /// @notice Called only for successfully defeated fraud challenges.
303
+ /// The fraud challenge is marked as resolved and the amount of
304
+ /// ether deposited by the challenger is sent to the treasury.
305
+ /// @dev Requirements:
306
+ /// - Must be called only for successfully defeated fraud challenges.
307
+ function resolveFraudChallenge(
308
+ BridgeState.Storage storage self,
309
+ bytes calldata walletPublicKey,
310
+ FraudChallenge storage challenge,
311
+ bytes32 sighash
312
+ ) internal {
237
313
  // Mark the challenge as resolved as it was successfully defeated
238
314
  challenge.resolved = true;
239
315
 
@@ -248,6 +324,7 @@ library Fraud {
248
324
  walletPublicKey.slice32(32)
249
325
  );
250
326
  bytes20 walletPubKeyHash = compressedWalletPublicKey.hash160View();
327
+
251
328
  // slither-disable-next-line reentrancy-events
252
329
  emit FraudChallengeDefeated(walletPubKeyHash, sighash);
253
330
  }
@@ -0,0 +1,112 @@
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 {BytesLib} from "@keep-network/bitcoin-spv-sol/contracts/BytesLib.sol";
19
+
20
+ /// @title Bridge wallet heartbeat
21
+ /// @notice The library establishes expected format for heartbeat messages
22
+ /// signed by wallet ECDSA signing group. Heartbeat messages are
23
+ /// constructed in such a way that they can not be used as a Bitcoin
24
+ /// transaction preimages.
25
+ /// @dev The smallest Bitcoin non-coinbase transaction is a one spending an
26
+ /// OP_TRUE anyonecanspend output and creating 1 OP_TRUE anyonecanspend
27
+ /// output. Such a transaction has 61 bytes (see `BitcoinTx` documentation):
28
+ /// 4 bytes for version
29
+ /// 1 byte for tx_in_count
30
+ /// 36 bytes for tx_in.previous_output
31
+ /// 1 byte for tx_in.script_bytes (value: 0)
32
+ /// 0 bytes for tx_in.signature_script
33
+ /// 4 bytes for tx_in.sequence
34
+ /// 1 byte for tx_out_count
35
+ /// 8 bytes for tx_out.value
36
+ /// 1 byte for tx_out.pk_script_bytes
37
+ /// 1 byte for tx_out.pk_script
38
+ /// 4 bytes for lock_time
39
+ ///
40
+ ///
41
+ /// The smallest Bitcoin coinbase transaction is a one creating
42
+ /// 1 OP_TRUE anyonecanspend output and having an empty coinbase script.
43
+ /// Such a transaction has 65 bytes:
44
+ /// 4 bytes for version
45
+ /// 1 byte for tx_in_count
46
+ /// 32 bytes for tx_in.hash (all 0x00)
47
+ /// 4 bytes for tx_in.index (all 0xff)
48
+ /// 1 byte for tx_in.script_bytes (value: 0)
49
+ /// 4 bytes for tx_in.height
50
+ /// 0 byte for tx_in.coinbase_script
51
+ /// 4 bytes for tx_in.sequence
52
+ /// 1 byte for tx_out_count
53
+ /// 8 bytes for tx_out.value
54
+ /// 1 byte for tx_out.pk_script_bytes
55
+ /// 1 byte for tx_out.pk_script
56
+ /// 4 bytes for lock_time
57
+ ///
58
+ ///
59
+ /// A SIGHASH flag is used to indicate which part of the transaction is
60
+ /// signed by the ECDSA signature. There are currently 3 flags:
61
+ /// SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and different combinations
62
+ /// of these flags.
63
+ ///
64
+ /// No matter the SIGHASH flag and no matter the combination, the following
65
+ /// fields from the transaction are always included in the constructed
66
+ /// preimage:
67
+ /// 4 bytes for version
68
+ /// 36 bytes for tx_in.previous_output (or tx_in.hash + tx_in.index for coinbase)
69
+ /// 4 bytes for lock_time
70
+ ///
71
+ /// Additionally, the last 4 bytes of the preimage determines the SIGHASH
72
+ /// flag.
73
+ ///
74
+ /// This is enough to say there is no way the preimage could be shorter
75
+ /// than 4 + 36 + 4 + 4 = 48 bytes.
76
+ ///
77
+ /// For this reason, we construct the heartbeat message, as a 16-byte
78
+ /// message. The first 8 bytes are 0xffffffffffffffff. The last 8 bytes
79
+ /// are for an arbitrary uint64, being a signed heartbeat nonce (for
80
+ /// example, the last Ethereum block hash).
81
+ ///
82
+ /// The message being signed by the wallet when executing the heartbeat
83
+ /// protocol should be Bitcoin's hash256 (double SHA-256) of the heartbeat
84
+ /// message:
85
+ /// heartbeat_sighash = hash256(heartbeat_message)
86
+ library Heartbeat {
87
+ using BytesLib for bytes;
88
+
89
+ /// @notice Determines if the signed byte array is a valid, non-fraudulent
90
+ /// heartbeat message.
91
+ /// @param message Message signed by the wallet. It is a potential heartbeat
92
+ /// message, Bitcoin transaction preimage, or an arbitrary signed
93
+ /// bytes
94
+ /// @dev Wallet heartbeat message must be exactly 16 bytes long with the first
95
+ /// 8 bytes set to 0xffffffffffffffff.
96
+ /// @return True if valid heartbeat message, false otherwise.
97
+ function isValidHeartbeatMessage(bytes calldata message)
98
+ internal
99
+ pure
100
+ returns (bool)
101
+ {
102
+ if (message.length != 16) {
103
+ return false;
104
+ }
105
+
106
+ if (message.slice8(0) != 0xffffffffffffffff) {
107
+ return false;
108
+ }
109
+
110
+ return true;
111
+ }
112
+ }
@@ -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(address owner, uint256 amount)
84
+ external
85
+ override
86
+ onlyBank
87
+ {
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
+ }
package/export.json CHANGED
@@ -14871,6 +14871,24 @@
14871
14871
  "stateMutability": "nonpayable",
14872
14872
  "type": "function"
14873
14873
  },
14874
+ {
14875
+ "inputs": [
14876
+ {
14877
+ "internalType": "bytes",
14878
+ "name": "walletPublicKey",
14879
+ "type": "bytes"
14880
+ },
14881
+ {
14882
+ "internalType": "bytes",
14883
+ "name": "heartbeatMessage",
14884
+ "type": "bytes"
14885
+ }
14886
+ ],
14887
+ "name": "defeatFraudChallengeWithHeartbeat",
14888
+ "outputs": [],
14889
+ "stateMutability": "nonpayable",
14890
+ "type": "function"
14891
+ },
14874
14892
  {
14875
14893
  "inputs": [],
14876
14894
  "name": "depositParameters",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keep-network/tbtc-v2",
3
- "version": "0.1.1-dev.60+main.89dbb465ebef3bee9f0d8ff369d3b0b8cde22427",
3
+ "version": "0.1.1-dev.63+main.68e692f8fe53043af3c81bd88afd16954759ad5d",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "artifacts/",