@keep-network/tbtc-v2 0.1.1-dev.1 → 0.1.1-dev.101

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 (125) 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/MovingFunds.json +249 -0
  17. package/artifacts/NuCypherStakingEscrow.json +256 -0
  18. package/artifacts/NuCypherToken.json +711 -0
  19. package/artifacts/RandomBeaconStub.json +141 -0
  20. package/artifacts/Redemption.json +174 -0
  21. package/artifacts/ReimbursementPool.json +509 -0
  22. package/artifacts/Relay.json +123 -0
  23. package/artifacts/T.json +1148 -0
  24. package/artifacts/TBTC.json +27 -26
  25. package/artifacts/TBTCToken.json +27 -26
  26. package/artifacts/TBTCVault.json +691 -0
  27. package/artifacts/TokenStaking.json +2288 -0
  28. package/artifacts/TokenholderGovernor.json +1795 -0
  29. package/artifacts/TokenholderTimelock.json +1058 -0
  30. package/artifacts/VendingMachine.json +31 -30
  31. package/artifacts/VendingMachineKeep.json +400 -0
  32. package/artifacts/VendingMachineNuCypher.json +400 -0
  33. package/artifacts/WalletRegistry.json +1843 -0
  34. package/artifacts/WalletRegistryGovernance.json +2754 -0
  35. package/artifacts/Wallets.json +186 -0
  36. package/artifacts/solcInputs/af641e0b3597cdfa29d6ad42d1cd8742.json +320 -0
  37. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  38. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.json +2 -2
  39. package/build/contracts/bank/Bank.sol/Bank.dbg.json +4 -0
  40. package/build/contracts/bank/Bank.sol/Bank.json +542 -0
  41. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.dbg.json +4 -0
  42. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.json +34 -0
  43. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +4 -0
  44. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +10 -0
  45. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +4 -0
  46. package/build/contracts/bridge/Bridge.sol/Bridge.json +2686 -0
  47. package/build/contracts/bridge/BridgeGovernance.sol/BridgeGovernance.dbg.json +4 -0
  48. package/build/contracts/bridge/BridgeGovernance.sol/BridgeGovernance.json +2246 -0
  49. package/build/contracts/bridge/BridgeGovernanceParameters.sol/BridgeGovernanceParameters.dbg.json +4 -0
  50. package/build/contracts/bridge/BridgeGovernanceParameters.sol/BridgeGovernanceParameters.json +971 -0
  51. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +4 -0
  52. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +226 -0
  53. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +4 -0
  54. package/build/contracts/bridge/Deposit.sol/Deposit.json +72 -0
  55. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +4 -0
  56. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +30 -0
  57. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +4 -0
  58. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.json +10 -0
  59. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +4 -0
  60. package/build/contracts/bridge/Fraud.sol/Fraud.json +86 -0
  61. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.dbg.json +4 -0
  62. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.json +10 -0
  63. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +4 -0
  64. package/build/contracts/bridge/IRelay.sol/IRelay.json +37 -0
  65. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +4 -0
  66. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +138 -0
  67. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +4 -0
  68. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +10 -0
  69. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +4 -0
  70. package/build/contracts/bridge/Redemption.sol/Redemption.json +92 -0
  71. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  72. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.json +2 -2
  73. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +4 -0
  74. package/build/contracts/bridge/Wallets.sol/Wallets.json +112 -0
  75. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  76. package/build/contracts/token/TBTC.sol/TBTC.json +2 -2
  77. package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +4 -0
  78. package/build/contracts/vault/DonationVault.sol/DonationVault.json +108 -0
  79. package/build/contracts/vault/IVault.sol/IVault.dbg.json +4 -0
  80. package/build/contracts/vault/IVault.sol/IVault.json +52 -0
  81. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +4 -0
  82. package/build/contracts/vault/TBTCVault.sol/TBTCVault.json +449 -0
  83. package/contracts/GovernanceUtils.sol +4 -4
  84. package/contracts/bank/Bank.sol +436 -0
  85. package/contracts/bank/IReceiveBalanceApproval.sol +45 -0
  86. package/contracts/bridge/BitcoinTx.sol +361 -0
  87. package/contracts/bridge/Bridge.sol +1799 -0
  88. package/contracts/bridge/BridgeGovernance.sol +1533 -0
  89. package/contracts/bridge/BridgeGovernanceParameters.sol +1695 -0
  90. package/contracts/bridge/BridgeState.sol +768 -0
  91. package/contracts/bridge/Deposit.sol +269 -0
  92. package/contracts/bridge/DepositSweep.sol +574 -0
  93. package/contracts/bridge/EcdsaLib.sol +45 -0
  94. package/contracts/bridge/Fraud.sol +579 -0
  95. package/contracts/bridge/Heartbeat.sol +112 -0
  96. package/contracts/bridge/IRelay.sol +28 -0
  97. package/contracts/bridge/MovingFunds.sol +1077 -0
  98. package/contracts/bridge/Redemption.sol +1058 -0
  99. package/contracts/bridge/VendingMachine.sol +2 -2
  100. package/contracts/bridge/Wallets.sol +719 -0
  101. package/contracts/hardhat-dependency-compiler/.hardhat-dependency-compiler +1 -0
  102. package/contracts/hardhat-dependency-compiler/@keep-network/ecdsa/contracts/WalletRegistry.sol +3 -0
  103. package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol +3 -0
  104. package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol +3 -0
  105. package/contracts/token/TBTC.sol +1 -1
  106. package/contracts/vault/DonationVault.sol +125 -0
  107. package/contracts/vault/IVault.sol +44 -0
  108. package/contracts/vault/TBTCVault.sol +305 -0
  109. package/deploy/00_resolve_relay.ts +28 -0
  110. package/deploy/{03_transfer_roles.ts → 03_transfer_vending_machine_roles.ts} +1 -1
  111. package/deploy/04_deploy_bank.ts +27 -0
  112. package/deploy/05_deploy_bridge.ts +80 -0
  113. package/deploy/06_deploy_tbtc_vault.ts +30 -0
  114. package/deploy/07_deploy_bridge_governance.ts +40 -0
  115. package/deploy/08_bank_update_bridge.ts +19 -0
  116. package/deploy/09_transfer_bank_ownership.ts +15 -0
  117. package/deploy/10_transfer_tbtc_vault_ownership.ts +15 -0
  118. package/deploy/11_transfer_bridge_governance_ownership.ts +19 -0
  119. package/deploy/12_transfer_bridge_governance.ts +22 -0
  120. package/deploy/13_initialize_wallet_owner.ts +18 -0
  121. package/deploy/14_deploy_proxy_admin_with_deputy.ts +33 -0
  122. package/deploy/15_transfer_proxy_admin_ownership.ts +30 -0
  123. package/export.json +18510 -475
  124. package/package.json +35 -26
  125. package/artifacts/solcInputs/0c46d22cee2363c42c8bb0664dc1be66.json +0 -104
@@ -0,0 +1,436 @@
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
+
20
+ import "./IReceiveBalanceApproval.sol";
21
+ import "../vault/IVault.sol";
22
+
23
+ /// @title Bitcoin Bank
24
+ /// @notice Bank is a central component tracking Bitcoin balances. Balances can
25
+ /// be transferred between balance owners, and balance owners can
26
+ /// approve their balances to be spent by others. Balances in the Bank
27
+ /// are updated for depositors who deposited their Bitcoin into the
28
+ /// Bridge and only the Bridge can increase balances.
29
+ /// @dev Bank is a governable contract and the Governance can upgrade the Bridge
30
+ /// address.
31
+ contract Bank is Ownable {
32
+ address public bridge;
33
+
34
+ /// @notice The balance of the given account in the Bank. Zero by default.
35
+ mapping(address => uint256) public balanceOf;
36
+
37
+ /// @notice The remaining amount of balance a spender will be
38
+ /// allowed to transfer on behalf of an owner using
39
+ /// `transferBalanceFrom`. Zero by default.
40
+ mapping(address => mapping(address => uint256)) public allowance;
41
+
42
+ /// @notice Returns the current nonce for an EIP2612 permission for the
43
+ /// provided balance owner to protect against replay attacks. Used
44
+ /// to construct an EIP2612 signature provided to the `permit`
45
+ /// function.
46
+ mapping(address => uint256) public nonce;
47
+
48
+ uint256 public immutable cachedChainId;
49
+ bytes32 public immutable cachedDomainSeparator;
50
+
51
+ /// @notice Returns an EIP2612 Permit message hash. Used to construct
52
+ /// an EIP2612 signature provided to the `permit` function.
53
+ bytes32 public constant PERMIT_TYPEHASH =
54
+ keccak256(
55
+ "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
56
+ );
57
+
58
+ event BalanceTransferred(
59
+ address indexed from,
60
+ address indexed to,
61
+ uint256 amount
62
+ );
63
+
64
+ event BalanceApproved(
65
+ address indexed owner,
66
+ address indexed spender,
67
+ uint256 amount
68
+ );
69
+
70
+ event BalanceIncreased(address indexed owner, uint256 amount);
71
+
72
+ event BalanceDecreased(address indexed owner, uint256 amount);
73
+
74
+ event BridgeUpdated(address newBridge);
75
+
76
+ modifier onlyBridge() {
77
+ require(msg.sender == address(bridge), "Caller is not the bridge");
78
+ _;
79
+ }
80
+
81
+ constructor() {
82
+ cachedChainId = block.chainid;
83
+ cachedDomainSeparator = buildDomainSeparator();
84
+ }
85
+
86
+ /// @notice Allows the Governance to upgrade the Bridge address.
87
+ /// @dev The function does not implement any governance delay and does not
88
+ /// check the status of the Bridge. The Governance implementation needs
89
+ /// to ensure all requirements for the upgrade are satisfied before
90
+ /// executing this function.
91
+ /// Requirements:
92
+ /// - The new Bridge address must not be zero.
93
+ /// @param _bridge The new Bridge address.
94
+ function updateBridge(address _bridge) external onlyOwner {
95
+ require(_bridge != address(0), "Bridge address must not be 0x0");
96
+ bridge = _bridge;
97
+ emit BridgeUpdated(_bridge);
98
+ }
99
+
100
+ /// @notice Moves the given `amount` of balance from the caller to
101
+ /// `recipient`.
102
+ /// @dev Requirements:
103
+ /// - `recipient` cannot be the zero address,
104
+ /// - the caller must have a balance of at least `amount`.
105
+ /// @param recipient The recipient of the balance.
106
+ /// @param amount The amount of the balance transferred.
107
+ function transferBalance(address recipient, uint256 amount) external {
108
+ _transferBalance(msg.sender, recipient, amount);
109
+ }
110
+
111
+ /// @notice Sets `amount` as the allowance of `spender` over the caller's
112
+ /// balance.
113
+ /// @dev If the `amount` is set to `type(uint256).max`,
114
+ /// `transferBalanceFrom` will not reduce an allowance.
115
+ /// Beware that changing an allowance with this function brings the
116
+ /// risk that someone may use both the old and the new allowance by
117
+ /// unfortunate transaction ordering. Please use
118
+ /// `increaseBalanceAllowance` and `decreaseBalanceAllowance` to
119
+ /// eliminate the risk.
120
+ /// @param spender The address that will be allowed to spend the balance.
121
+ /// @param amount The amount the spender is allowed to spend.
122
+ function approveBalance(address spender, uint256 amount) external {
123
+ _approveBalance(msg.sender, spender, amount);
124
+ }
125
+
126
+ /// @notice Sets the `amount` as an allowance of a smart contract `spender`
127
+ /// over the caller's balance and calls the `spender` via
128
+ /// `receiveBalanceApproval`.
129
+ /// @dev If the `amount` is set to `type(uint256).max`, the potential
130
+ /// `transferBalanceFrom` executed in `receiveBalanceApproval` of
131
+ /// `spender` will not reduce an allowance. Beware that changing an
132
+ /// allowance with this function brings the risk that `spender` may use
133
+ /// both the old and the new allowance by unfortunate transaction
134
+ /// ordering. Please use `increaseBalanceAllowance` and
135
+ /// `decreaseBalanceAllowance` to eliminate the risk.
136
+ /// @param spender The smart contract that will be allowed to spend the
137
+ /// balance.
138
+ /// @param amount The amount the spender contract is allowed to spend.
139
+ /// @param extraData Extra data passed to the `spender` contract via
140
+ /// `receiveBalanceApproval` call.
141
+ function approveBalanceAndCall(
142
+ address spender,
143
+ uint256 amount,
144
+ bytes calldata extraData
145
+ ) external {
146
+ _approveBalance(msg.sender, spender, amount);
147
+ IReceiveBalanceApproval(spender).receiveBalanceApproval(
148
+ msg.sender,
149
+ amount,
150
+ extraData
151
+ );
152
+ }
153
+
154
+ /// @notice Atomically increases the caller's balance allowance granted to
155
+ /// `spender` by the given `addedValue`.
156
+ /// @param spender The spender address for which the allowance is increased.
157
+ /// @param addedValue The amount by which the allowance is increased.
158
+ function increaseBalanceAllowance(address spender, uint256 addedValue)
159
+ external
160
+ {
161
+ _approveBalance(
162
+ msg.sender,
163
+ spender,
164
+ allowance[msg.sender][spender] + addedValue
165
+ );
166
+ }
167
+
168
+ /// @notice Atomically decreases the caller's balance allowance granted to
169
+ /// `spender` by the given `subtractedValue`.
170
+ /// @dev Requirements:
171
+ /// - `spender` must not be the zero address,
172
+ /// - the current allowance for `spender` must not be lower than
173
+ /// the `subtractedValue`.
174
+ /// @param spender The spender address for which the allowance is decreased.
175
+ /// @param subtractedValue The amount by which the allowance is decreased.
176
+ function decreaseBalanceAllowance(address spender, uint256 subtractedValue)
177
+ external
178
+ {
179
+ uint256 currentAllowance = allowance[msg.sender][spender];
180
+ require(
181
+ currentAllowance >= subtractedValue,
182
+ "Can not decrease balance allowance below zero"
183
+ );
184
+ unchecked {
185
+ _approveBalance(
186
+ msg.sender,
187
+ spender,
188
+ currentAllowance - subtractedValue
189
+ );
190
+ }
191
+ }
192
+
193
+ /// @notice Moves `amount` of balance from `spender` to `recipient` using the
194
+ /// allowance mechanism. `amount` is then deducted from the caller's
195
+ /// allowance unless the allowance was made for `type(uint256).max`.
196
+ /// @dev Requirements:
197
+ /// - `recipient` cannot be the zero address,
198
+ /// - `spender` must have a balance of at least `amount`,
199
+ /// - the caller must have an allowance for `spender`'s balance of at
200
+ /// least `amount`.
201
+ /// @param spender The address from which the balance is transferred.
202
+ /// @param recipient The address to which the balance is transferred.
203
+ /// @param amount The amount of balance that is transferred.
204
+ function transferBalanceFrom(
205
+ address spender,
206
+ address recipient,
207
+ uint256 amount
208
+ ) external {
209
+ uint256 currentAllowance = allowance[spender][msg.sender];
210
+ if (currentAllowance != type(uint256).max) {
211
+ require(
212
+ currentAllowance >= amount,
213
+ "Transfer amount exceeds allowance"
214
+ );
215
+ unchecked {
216
+ _approveBalance(spender, msg.sender, currentAllowance - amount);
217
+ }
218
+ }
219
+ _transferBalance(spender, recipient, amount);
220
+ }
221
+
222
+ /// @notice An EIP2612 approval made with secp256k1 signature. Users can
223
+ /// authorize a transfer of their balance with a signature
224
+ /// conforming to the EIP712 standard, rather than an on-chain
225
+ /// transaction from their address. Anyone can submit this signature
226
+ /// on the user's behalf by calling the `permit` function, paying
227
+ /// gas fees, and possibly performing other actions in the same
228
+ /// transaction.
229
+ /// @dev The deadline argument can be set to `type(uint256).max to create
230
+ /// permits that effectively never expire. If the `amount` is set
231
+ /// to `type(uint256).max` then `transferBalanceFrom` will not
232
+ /// reduce an allowance. Beware that changing an allowance with this
233
+ /// function brings the risk that someone may use both the old and the
234
+ /// new allowance by unfortunate transaction ordering. Please use
235
+ /// `increaseBalanceAllowance` and `decreaseBalanceAllowance` to
236
+ /// eliminate the risk.
237
+ /// @param owner The balance owner who signed the permission.
238
+ /// @param spender The address that will be allowed to spend the balance.
239
+ /// @param amount The amount the spender is allowed to spend.
240
+ /// @param deadline The UNIX time until which the permit is valid.
241
+ /// @param v V part of the permit signature.
242
+ /// @param r R part of the permit signature.
243
+ /// @param s S part of the permit signature.
244
+ function permit(
245
+ address owner,
246
+ address spender,
247
+ uint256 amount,
248
+ uint256 deadline,
249
+ uint8 v,
250
+ bytes32 r,
251
+ bytes32 s
252
+ ) external {
253
+ /* solhint-disable-next-line not-rely-on-time */
254
+ require(deadline >= block.timestamp, "Permission expired");
255
+
256
+ // Validate `s` and `v` values for a malleability concern described in EIP2.
257
+ // Only signatures with `s` value in the lower half of the secp256k1
258
+ // curve's order and `v` value of 27 or 28 are considered valid.
259
+ require(
260
+ uint256(s) <=
261
+ 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
262
+ "Invalid signature 's' value"
263
+ );
264
+ require(v == 27 || v == 28, "Invalid signature 'v' value");
265
+
266
+ bytes32 digest = keccak256(
267
+ abi.encodePacked(
268
+ "\x19\x01",
269
+ DOMAIN_SEPARATOR(),
270
+ keccak256(
271
+ abi.encode(
272
+ PERMIT_TYPEHASH,
273
+ owner,
274
+ spender,
275
+ amount,
276
+ nonce[owner]++,
277
+ deadline
278
+ )
279
+ )
280
+ )
281
+ );
282
+ address recoveredAddress = ecrecover(digest, v, r, s);
283
+ require(
284
+ recoveredAddress != address(0) && recoveredAddress == owner,
285
+ "Invalid signature"
286
+ );
287
+ _approveBalance(owner, spender, amount);
288
+ }
289
+
290
+ /// @notice Increases balances of the provided `recipients` by the provided
291
+ /// `amounts`. Can only be called by the Bridge.
292
+ /// @dev Requirements:
293
+ /// - length of `recipients` and `amounts` must be the same,
294
+ /// - none of `recipients` addresses must point to the Bank.
295
+ /// @param recipients Balance increase recipients.
296
+ /// @param amounts Amounts by which balances are increased.
297
+ function increaseBalances(
298
+ address[] calldata recipients,
299
+ uint256[] calldata amounts
300
+ ) external onlyBridge {
301
+ require(
302
+ recipients.length == amounts.length,
303
+ "Arrays must have the same length"
304
+ );
305
+ for (uint256 i = 0; i < recipients.length; i++) {
306
+ _increaseBalance(recipients[i], amounts[i]);
307
+ }
308
+ }
309
+
310
+ /// @notice Increases balance of the provided `recipient` by the provided
311
+ /// `amount`. Can only be called by the Bridge.
312
+ /// @dev Requirements:
313
+ /// - `recipient` address must not point to the Bank.
314
+ /// @param recipient Balance increase recipient.
315
+ /// @param amount Amount by which the balance is increased.
316
+ function increaseBalance(address recipient, uint256 amount)
317
+ external
318
+ onlyBridge
319
+ {
320
+ _increaseBalance(recipient, amount);
321
+ }
322
+
323
+ /// @notice Increases the given smart contract `vault`'s balance and
324
+ /// notifies the `vault` contract about it.
325
+ /// Can be called only by the Bridge.
326
+ /// @dev Requirements:
327
+ /// - `vault` must implement `IVault` interface,
328
+ /// - length of `recipients` and `amounts` must be the same.
329
+ /// @param vault Address of `IVault` recipient contract.
330
+ /// @param recipients Balance increase recipients.
331
+ /// @param amounts Amounts by which balances are increased.
332
+ function increaseBalanceAndCall(
333
+ address vault,
334
+ address[] calldata recipients,
335
+ uint256[] calldata amounts
336
+ ) external onlyBridge {
337
+ require(
338
+ recipients.length == amounts.length,
339
+ "Arrays must have the same length"
340
+ );
341
+ uint256 totalAmount = 0;
342
+ for (uint256 i = 0; i < amounts.length; i++) {
343
+ totalAmount += amounts[i];
344
+ }
345
+ _increaseBalance(vault, totalAmount);
346
+ IVault(vault).receiveBalanceIncrease(recipients, amounts);
347
+ }
348
+
349
+ /// @notice Decreases caller's balance by the provided `amount`. There is no
350
+ /// way to restore the balance so do not call this function unless
351
+ /// you really know what you are doing!
352
+ /// @dev Requirements:
353
+ /// - The caller must have a balance of at least `amount`.
354
+ /// @param amount The amount by which the balance is decreased.
355
+ function decreaseBalance(uint256 amount) external {
356
+ balanceOf[msg.sender] -= amount;
357
+ emit BalanceDecreased(msg.sender, amount);
358
+ }
359
+
360
+ /// @notice Returns hash of EIP712 Domain struct with `TBTC Bank` as
361
+ /// a signing domain and Bank contract as a verifying contract.
362
+ /// Used to construct an EIP2612 signature provided to the `permit`
363
+ /// function.
364
+ /* solhint-disable-next-line func-name-mixedcase */
365
+ function DOMAIN_SEPARATOR() public view returns (bytes32) {
366
+ // As explained in EIP-2612, if the DOMAIN_SEPARATOR contains the
367
+ // chainId and is defined at contract deployment instead of
368
+ // reconstructed for every signature, there is a risk of possible replay
369
+ // attacks between chains in the event of a future chain split.
370
+ // To address this issue, we check the cached chain ID against the
371
+ // current one and in case they are different, we build domain separator
372
+ // from scratch.
373
+ if (block.chainid == cachedChainId) {
374
+ return cachedDomainSeparator;
375
+ } else {
376
+ return buildDomainSeparator();
377
+ }
378
+ }
379
+
380
+ function _increaseBalance(address recipient, uint256 amount) internal {
381
+ require(
382
+ recipient != address(this),
383
+ "Can not increase balance for Bank"
384
+ );
385
+ balanceOf[recipient] += amount;
386
+ emit BalanceIncreased(recipient, amount);
387
+ }
388
+
389
+ function _transferBalance(
390
+ address spender,
391
+ address recipient,
392
+ uint256 amount
393
+ ) private {
394
+ require(
395
+ recipient != address(0),
396
+ "Can not transfer to the zero address"
397
+ );
398
+ require(
399
+ recipient != address(this),
400
+ "Can not transfer to the Bank address"
401
+ );
402
+
403
+ uint256 spenderBalance = balanceOf[spender];
404
+ require(spenderBalance >= amount, "Transfer amount exceeds balance");
405
+ unchecked {
406
+ balanceOf[spender] = spenderBalance - amount;
407
+ }
408
+ balanceOf[recipient] += amount;
409
+ emit BalanceTransferred(spender, recipient, amount);
410
+ }
411
+
412
+ function _approveBalance(
413
+ address owner,
414
+ address spender,
415
+ uint256 amount
416
+ ) private {
417
+ require(spender != address(0), "Can not approve to the zero address");
418
+ allowance[owner][spender] = amount;
419
+ emit BalanceApproved(owner, spender, amount);
420
+ }
421
+
422
+ function buildDomainSeparator() private view returns (bytes32) {
423
+ return
424
+ keccak256(
425
+ abi.encode(
426
+ keccak256(
427
+ "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
428
+ ),
429
+ keccak256(bytes("TBTC Bank")),
430
+ keccak256(bytes("1")),
431
+ block.chainid,
432
+ address(this)
433
+ )
434
+ );
435
+ }
436
+ }
@@ -0,0 +1,45 @@
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
+ /// @title IReceiveBalanceApproval
19
+ /// @notice `IReceiveBalanceApproval` is an interface for a smart contract
20
+ /// consuming Bank balances approved to them in the same transaction by
21
+ /// other contracts or externally owned accounts (EOA).
22
+ interface IReceiveBalanceApproval {
23
+ /// @notice Called by the Bank in `approveBalanceAndCall` function after
24
+ /// the balance `owner` approved `amount` of their balance in the
25
+ /// Bank for the contract. This way, the depositor can approve
26
+ /// balance and call the contract to use the approved balance in
27
+ /// a single transaction.
28
+ /// @param owner Address of the Bank balance owner who approved their
29
+ /// balance to be used by the contract.
30
+ /// @param amount The amount of the Bank balance approved by the owner
31
+ /// to be used by the contract.
32
+ /// @param extraData The `extraData` passed to `Bank.approveBalanceAndCall`.
33
+ /// @dev The implementation must ensure this function can only be called
34
+ /// by the Bank. The Bank does _not_ guarantee that the `amount`
35
+ /// approved by the `owner` currently exists on their balance. That is,
36
+ /// the `owner` could approve more balance than they currently have.
37
+ /// This works the same as `Bank.approve` function. The contract must
38
+ /// ensure the actual balance is checked before performing any action
39
+ /// based on it.
40
+ function receiveBalanceApproval(
41
+ address owner,
42
+ uint256 amount,
43
+ bytes calldata extraData
44
+ ) external;
45
+ }