@keep-network/tbtc-v2 0.1.0 → 0.1.1-dev

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 (296) hide show
  1. package/README.adoc +12 -0
  2. package/artifacts/.chainId +1 -1
  3. package/artifacts/Bank.json +807 -0
  4. package/artifacts/Bridge.json +2300 -0
  5. package/artifacts/Deposit.json +117 -0
  6. package/artifacts/DepositSweep.json +77 -0
  7. package/artifacts/EcdsaDkgValidator.json +532 -0
  8. package/artifacts/EcdsaInactivity.json +156 -0
  9. package/artifacts/EcdsaSortitionPool.json +1004 -0
  10. package/artifacts/Fraud.json +164 -0
  11. package/artifacts/KeepRegistry.json +99 -0
  12. package/artifacts/KeepStake.json +286 -0
  13. package/artifacts/KeepToken.json +711 -0
  14. package/artifacts/KeepTokenStaking.json +483 -0
  15. package/artifacts/MovingFunds.json +249 -0
  16. package/artifacts/NuCypherStakingEscrow.json +256 -0
  17. package/artifacts/NuCypherToken.json +711 -0
  18. package/artifacts/RandomBeaconStub.json +141 -0
  19. package/artifacts/Redemption.json +174 -0
  20. package/artifacts/ReimbursementPool.json +509 -0
  21. package/artifacts/Relay.json +123 -0
  22. package/artifacts/T.json +1148 -0
  23. package/artifacts/TBTC.json +36 -35
  24. package/artifacts/TBTCToken.json +738 -0
  25. package/artifacts/TBTCVault.json +691 -0
  26. package/artifacts/TokenStaking.json +2288 -0
  27. package/artifacts/TokenholderGovernor.json +1795 -0
  28. package/artifacts/TokenholderTimelock.json +1058 -0
  29. package/artifacts/VendingMachine.json +34 -33
  30. package/artifacts/VendingMachineKeep.json +400 -0
  31. package/artifacts/VendingMachineNuCypher.json +400 -0
  32. package/artifacts/WalletRegistry.json +1843 -0
  33. package/artifacts/WalletRegistryGovernance.json +2754 -0
  34. package/artifacts/Wallets.json +186 -0
  35. package/artifacts/solcInputs/5e62cff1ead0900b07facca4b559e818.json +314 -0
  36. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  37. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.json +2 -2
  38. package/build/contracts/bank/Bank.sol/Bank.dbg.json +4 -0
  39. package/build/contracts/bank/Bank.sol/Bank.json +542 -0
  40. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.dbg.json +4 -0
  41. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.json +34 -0
  42. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +4 -0
  43. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +10 -0
  44. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +4 -0
  45. package/build/contracts/bridge/Bridge.sol/Bridge.json +2686 -0
  46. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +4 -0
  47. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +226 -0
  48. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +4 -0
  49. package/build/contracts/bridge/Deposit.sol/Deposit.json +72 -0
  50. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +4 -0
  51. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +30 -0
  52. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +4 -0
  53. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.json +10 -0
  54. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +4 -0
  55. package/build/contracts/bridge/Fraud.sol/Fraud.json +86 -0
  56. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.dbg.json +4 -0
  57. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.json +10 -0
  58. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +4 -0
  59. package/build/contracts/bridge/IRelay.sol/IRelay.json +37 -0
  60. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +4 -0
  61. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +138 -0
  62. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +4 -0
  63. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +10 -0
  64. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +4 -0
  65. package/build/contracts/bridge/Redemption.sol/Redemption.json +92 -0
  66. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  67. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.json +2 -2
  68. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +4 -0
  69. package/build/contracts/bridge/Wallets.sol/Wallets.json +112 -0
  70. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  71. package/build/contracts/token/TBTC.sol/TBTC.json +4 -4
  72. package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +4 -0
  73. package/build/contracts/vault/DonationVault.sol/DonationVault.json +108 -0
  74. package/build/contracts/vault/IVault.sol/IVault.dbg.json +4 -0
  75. package/build/contracts/vault/IVault.sol/IVault.json +52 -0
  76. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +4 -0
  77. package/build/contracts/vault/TBTCVault.sol/TBTCVault.json +449 -0
  78. package/contracts/GovernanceUtils.sol +4 -4
  79. package/contracts/bank/Bank.sol +436 -0
  80. package/contracts/bank/IReceiveBalanceApproval.sol +45 -0
  81. package/contracts/bridge/BitcoinTx.sol +326 -0
  82. package/contracts/bridge/Bridge.sol +1793 -0
  83. package/contracts/bridge/BridgeState.sol +739 -0
  84. package/contracts/bridge/Deposit.sol +269 -0
  85. package/contracts/bridge/DepositSweep.sol +574 -0
  86. package/contracts/bridge/EcdsaLib.sol +45 -0
  87. package/contracts/bridge/Fraud.sol +579 -0
  88. package/contracts/bridge/Heartbeat.sol +112 -0
  89. package/contracts/bridge/IRelay.sol +28 -0
  90. package/contracts/bridge/MovingFunds.sol +1077 -0
  91. package/contracts/bridge/Redemption.sol +1020 -0
  92. package/contracts/bridge/VendingMachine.sol +2 -2
  93. package/contracts/bridge/Wallets.sol +719 -0
  94. package/contracts/hardhat-dependency-compiler/.hardhat-dependency-compiler +1 -0
  95. package/contracts/hardhat-dependency-compiler/@keep-network/ecdsa/contracts/WalletRegistry.sol +3 -0
  96. package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol +3 -0
  97. package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol +3 -0
  98. package/contracts/token/TBTC.sol +1 -1
  99. package/contracts/vault/DonationVault.sol +125 -0
  100. package/contracts/vault/IVault.sol +44 -0
  101. package/contracts/vault/TBTCVault.sol +305 -0
  102. package/deploy/00_resolve_relay.ts +28 -0
  103. package/deploy/00_resolve_tbtc_v1_token.ts +1 -1
  104. package/deploy/01_deploy_tbtc_v2_token.ts +8 -1
  105. package/deploy/02_deploy_vending_machine.ts +7 -0
  106. package/deploy/{03_transfer_roles.ts → 03_transfer_vending_machine_roles.ts} +1 -1
  107. package/deploy/04_deploy_bank.ts +27 -0
  108. package/deploy/05_deploy_bridge.ts +80 -0
  109. package/deploy/06_deploy_tbtc_vault.ts +30 -0
  110. package/deploy/07_bank_update_bridge.ts +19 -0
  111. package/deploy/08_transfer_bank_ownership.ts +15 -0
  112. package/deploy/09_transfer_tbtc_vault_ownership.ts +15 -0
  113. package/deploy/10_transfer_bridge_governance.ts +20 -0
  114. package/deploy/11_initialize_wallet_owner.ts +18 -0
  115. package/deploy/11_transfer_proxy_admin_ownership.ts +30 -0
  116. package/deploy/12_deploy_proxy_admin_with_deputy.ts +33 -0
  117. package/export/deploy/00_resolve_relay.js +24 -0
  118. package/export/deploy/00_resolve_tbtc_v1_token.js +24 -0
  119. package/export/deploy/01_deploy_tbtc_v2_token.js +19 -0
  120. package/export/deploy/02_deploy_vending_machine.js +25 -0
  121. package/export/deploy/03_transfer_vending_machine_roles.js +19 -0
  122. package/export/deploy/04_deploy_bank.js +21 -0
  123. package/export/deploy/05_deploy_bridge.js +69 -0
  124. package/export/deploy/06_deploy_tbtc_vault.js +24 -0
  125. package/export/deploy/07_bank_update_bridge.js +13 -0
  126. package/export/deploy/08_transfer_bank_ownership.js +11 -0
  127. package/export/deploy/09_transfer_tbtc_vault_ownership.js +11 -0
  128. package/export/deploy/10_transfer_bridge_governance.js +11 -0
  129. package/export/deploy/11_initialize_wallet_owner.js +14 -0
  130. package/export/deploy/11_transfer_proxy_admin_ownership.js +23 -0
  131. package/export/deploy/12_deploy_proxy_admin_with_deputy.js +22 -0
  132. package/export/hardhat.config.js +169 -0
  133. package/export/test/bank/Bank.test.js +1012 -0
  134. package/export/test/bridge/Bridge.Deployment.test.js +76 -0
  135. package/export/test/bridge/Bridge.Deposit.test.js +1834 -0
  136. package/export/test/bridge/Bridge.Frauds.test.js +1349 -0
  137. package/export/test/bridge/Bridge.MovingFunds.test.js +2437 -0
  138. package/export/test/bridge/Bridge.Parameters.test.js +400 -0
  139. package/export/test/bridge/Bridge.Redemption.test.js +2523 -0
  140. package/export/test/bridge/Bridge.Vaults.test.js +74 -0
  141. package/export/test/bridge/Bridge.Wallets.test.js +1017 -0
  142. package/export/test/bridge/EcdsaLib.test.js +46 -0
  143. package/export/test/bridge/Heartbeat.test.js +77 -0
  144. package/export/test/bridge/VendingMachine.Upgrade.test.js +160 -0
  145. package/export/test/bridge/VendingMachine.test.js +762 -0
  146. package/export/test/data/deposit-sweep.js +655 -0
  147. package/export/test/data/ecdsa.js +18 -0
  148. package/export/test/data/fraud.js +158 -0
  149. package/export/test/data/moving-funds.js +815 -0
  150. package/export/test/data/redemption.js +1011 -0
  151. package/export/test/fixtures/bridge.js +54 -0
  152. package/export/test/fixtures/index.js +57 -0
  153. package/export/test/helpers/contract-test-helpers.js +18 -0
  154. package/export/test/integration/Slashing.test.js +279 -0
  155. package/export/test/integration/WalleCreation.test.js +66 -0
  156. package/export/test/integration/utils/ecdsa-wallet-registry.js +137 -0
  157. package/export/test/integration/utils/fixture.js +77 -0
  158. package/export/test/integration/utils/gas.js +36 -0
  159. package/export/test/integration/utils/random-beacon.js +26 -0
  160. package/export/test/integration/utils/staking.js +19 -0
  161. package/export/test/vault/DonationVault.test.js +202 -0
  162. package/export/test/vault/TBTCVault.Redemption.test.js +357 -0
  163. package/export/test/vault/TBTCVault.test.js +768 -0
  164. package/export/typechain/BTCUtils.js +2 -0
  165. package/export/typechain/Bank.js +2 -0
  166. package/export/typechain/BankStub.js +2 -0
  167. package/export/typechain/Bridge.js +2 -0
  168. package/export/typechain/BridgeState.js +2 -0
  169. package/export/typechain/BridgeStub.js +2 -0
  170. package/export/typechain/Deposit.js +2 -0
  171. package/export/typechain/DepositSweep.js +2 -0
  172. package/export/typechain/DonationVault.js +2 -0
  173. package/export/typechain/ERC165.js +2 -0
  174. package/export/typechain/ERC1967Proxy.js +2 -0
  175. package/export/typechain/ERC1967Upgrade.js +2 -0
  176. package/export/typechain/ERC20WithPermit.js +2 -0
  177. package/export/typechain/ERC721.js +2 -0
  178. package/export/typechain/EcdsaAuthorization.js +2 -0
  179. package/export/typechain/EcdsaDkg.js +2 -0
  180. package/export/typechain/EcdsaDkgValidator.js +2 -0
  181. package/export/typechain/EcdsaInactivity.js +2 -0
  182. package/export/typechain/Fraud.js +2 -0
  183. package/export/typechain/Governable.js +2 -0
  184. package/export/typechain/HeartbeatStub.js +2 -0
  185. package/export/typechain/IApplication.js +2 -0
  186. package/export/typechain/IApproveAndCall.js +2 -0
  187. package/export/typechain/IBeacon.js +2 -0
  188. package/export/typechain/IERC165.js +2 -0
  189. package/export/typechain/IERC1822Proxiable.js +2 -0
  190. package/export/typechain/IERC20.js +2 -0
  191. package/export/typechain/IERC20Metadata.js +2 -0
  192. package/export/typechain/IERC20WithPermit.js +2 -0
  193. package/export/typechain/IERC721.js +2 -0
  194. package/export/typechain/IERC721Metadata.js +2 -0
  195. package/export/typechain/IERC721Receiver.js +2 -0
  196. package/export/typechain/IRandomBeacon.js +2 -0
  197. package/export/typechain/IRandomBeaconConsumer.js +2 -0
  198. package/export/typechain/IReceiveApproval.js +2 -0
  199. package/export/typechain/IReceiveBalanceApproval.js +2 -0
  200. package/export/typechain/IRelay.js +2 -0
  201. package/export/typechain/IStaking.js +2 -0
  202. package/export/typechain/IVault.js +2 -0
  203. package/export/typechain/IWalletOwner.js +2 -0
  204. package/export/typechain/IWalletRegistry.js +2 -0
  205. package/export/typechain/Initializable.js +2 -0
  206. package/export/typechain/MisfundRecovery.js +2 -0
  207. package/export/typechain/MovingFunds.js +2 -0
  208. package/export/typechain/Ownable.js +2 -0
  209. package/export/typechain/Proxy.js +2 -0
  210. package/export/typechain/ProxyAdmin.js +2 -0
  211. package/export/typechain/ReceiveApprovalStub.js +2 -0
  212. package/export/typechain/Redemption.js +2 -0
  213. package/export/typechain/Reimbursable.js +2 -0
  214. package/export/typechain/ReimbursementPool.js +2 -0
  215. package/export/typechain/Rewards.js +2 -0
  216. package/export/typechain/SortitionPool.js +2 -0
  217. package/export/typechain/SortitionTree.js +2 -0
  218. package/export/typechain/TBTC.js +2 -0
  219. package/export/typechain/TBTCVault.js +2 -0
  220. package/export/typechain/TestERC20.js +2 -0
  221. package/export/typechain/TestERC721.js +2 -0
  222. package/export/typechain/TestEcdsaLib.js +2 -0
  223. package/export/typechain/TestRelay.js +2 -0
  224. package/export/typechain/TransparentUpgradeableProxy.js +2 -0
  225. package/export/typechain/VendingMachine.js +2 -0
  226. package/export/typechain/WalletRegistry.js +2 -0
  227. package/export/typechain/Wallets.js +2 -0
  228. package/export/typechain/common.js +2 -0
  229. package/export/typechain/factories/BTCUtils__factory.js +94 -0
  230. package/export/typechain/factories/BankStub__factory.js +586 -0
  231. package/export/typechain/factories/Bank__factory.js +573 -0
  232. package/export/typechain/factories/BridgeState__factory.js +257 -0
  233. package/export/typechain/factories/BridgeStub__factory.js +2912 -0
  234. package/export/typechain/factories/Bridge__factory.js +2526 -0
  235. package/export/typechain/factories/DepositSweep__factory.js +61 -0
  236. package/export/typechain/factories/Deposit__factory.js +103 -0
  237. package/export/typechain/factories/DonationVault__factory.js +139 -0
  238. package/export/typechain/factories/ERC165__factory.js +38 -0
  239. package/export/typechain/factories/ERC1967Proxy__factory.js +111 -0
  240. package/export/typechain/factories/ERC1967Upgrade__factory.js +64 -0
  241. package/export/typechain/factories/ERC20WithPermit__factory.js +524 -0
  242. package/export/typechain/factories/ERC721__factory.js +388 -0
  243. package/export/typechain/factories/EcdsaAuthorization__factory.js +211 -0
  244. package/export/typechain/factories/EcdsaDkgValidator__factory.js +441 -0
  245. package/export/typechain/factories/EcdsaDkg__factory.js +192 -0
  246. package/export/typechain/factories/EcdsaInactivity__factory.js +134 -0
  247. package/export/typechain/factories/Fraud__factory.js +117 -0
  248. package/export/typechain/factories/Governable__factory.js +64 -0
  249. package/export/typechain/factories/HeartbeatStub__factory.js +61 -0
  250. package/export/typechain/factories/IApplication__factory.js +152 -0
  251. package/export/typechain/factories/IApproveAndCall__factory.js +48 -0
  252. package/export/typechain/factories/IBeacon__factory.js +32 -0
  253. package/export/typechain/factories/IERC165__factory.js +38 -0
  254. package/export/typechain/factories/IERC1822Proxiable__factory.js +32 -0
  255. package/export/typechain/factories/IERC20Metadata__factory.js +241 -0
  256. package/export/typechain/factories/IERC20WithPermit__factory.js +389 -0
  257. package/export/typechain/factories/IERC20__factory.js +202 -0
  258. package/export/typechain/factories/IERC721Metadata__factory.js +349 -0
  259. package/export/typechain/factories/IERC721Receiver__factory.js +53 -0
  260. package/export/typechain/factories/IERC721__factory.js +304 -0
  261. package/export/typechain/factories/IRandomBeaconConsumer__factory.js +37 -0
  262. package/export/typechain/factories/IRandomBeacon__factory.js +32 -0
  263. package/export/typechain/factories/IReceiveApproval__factory.js +47 -0
  264. package/export/typechain/factories/IReceiveBalanceApproval__factory.js +42 -0
  265. package/export/typechain/factories/IRelay__factory.js +45 -0
  266. package/export/typechain/factories/IStaking__factory.js +722 -0
  267. package/export/typechain/factories/IVault__factory.js +60 -0
  268. package/export/typechain/factories/IWalletOwner__factory.js +65 -0
  269. package/export/typechain/factories/IWalletRegistry__factory.js +138 -0
  270. package/export/typechain/factories/Initializable__factory.js +32 -0
  271. package/export/typechain/factories/MisfundRecovery__factory.js +145 -0
  272. package/export/typechain/factories/MovingFunds__factory.js +169 -0
  273. package/export/typechain/factories/Ownable__factory.js +71 -0
  274. package/export/typechain/factories/ProxyAdmin__factory.js +191 -0
  275. package/export/typechain/factories/Proxy__factory.js +27 -0
  276. package/export/typechain/factories/ReceiveApprovalStub__factory.js +127 -0
  277. package/export/typechain/factories/Redemption__factory.js +123 -0
  278. package/export/typechain/factories/Reimbursable__factory.js +58 -0
  279. package/export/typechain/factories/ReimbursementPool__factory.js +350 -0
  280. package/export/typechain/factories/Rewards__factory.js +117 -0
  281. package/export/typechain/factories/SortitionPool__factory.js +610 -0
  282. package/export/typechain/factories/SortitionTree__factory.js +149 -0
  283. package/export/typechain/factories/TBTCVault__factory.js +480 -0
  284. package/export/typechain/factories/TBTC__factory.js +564 -0
  285. package/export/typechain/factories/TestERC20__factory.js +539 -0
  286. package/export/typechain/factories/TestERC721__factory.js +421 -0
  287. package/export/typechain/factories/TestEcdsaLib__factory.js +66 -0
  288. package/export/typechain/factories/TestRelay__factory.js +94 -0
  289. package/export/typechain/factories/TransparentUpgradeableProxy__factory.js +186 -0
  290. package/export/typechain/factories/VendingMachine__factory.js +549 -0
  291. package/export/typechain/factories/WalletRegistry__factory.js +1919 -0
  292. package/export/typechain/factories/Wallets__factory.js +143 -0
  293. package/export/typechain/index.js +132 -0
  294. package/export.json +15932 -503
  295. package/package.json +47 -26
  296. package/artifacts/solcInputs/7cc3eda3cb3ff2522d18b5e7b31ea228.json +0 -104
@@ -0,0 +1,768 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const hardhat_1 = require("hardhat");
4
+ const chai_1 = require("chai");
5
+ const { to1e18 } = hardhat_1.helpers.number;
6
+ const { createSnapshot, restoreSnapshot } = hardhat_1.helpers.snapshot;
7
+ const { increaseTime, lastBlockTime } = hardhat_1.helpers.time;
8
+ const ZERO_ADDRESS = hardhat_1.ethers.constants.AddressZero;
9
+ const fixture = async () => {
10
+ const [deployer, bridge, governance] = await hardhat_1.ethers.getSigners();
11
+ const Bank = await hardhat_1.ethers.getContractFactory("Bank");
12
+ const bank = await Bank.deploy();
13
+ await bank.deployed();
14
+ await bank.connect(deployer).updateBridge(bridge.address);
15
+ const TBTC = await hardhat_1.ethers.getContractFactory("TBTC");
16
+ const tbtc = await TBTC.deploy();
17
+ await tbtc.deployed();
18
+ const TBTCVault = await hardhat_1.ethers.getContractFactory("TBTCVault");
19
+ const vault = await TBTCVault.deploy(bank.address, tbtc.address);
20
+ await vault.deployed();
21
+ await tbtc.connect(deployer).transferOwnership(vault.address);
22
+ await vault.connect(deployer).transferOwnership(governance.address);
23
+ return {
24
+ bridge,
25
+ governance,
26
+ bank,
27
+ vault,
28
+ tbtc,
29
+ };
30
+ };
31
+ describe("TBTCVault", () => {
32
+ let bridge;
33
+ let governance;
34
+ let bank;
35
+ let vault;
36
+ let tbtc;
37
+ const initialBalance = to1e18(100);
38
+ let account1;
39
+ let account2;
40
+ before(async () => {
41
+ // eslint-disable-next-line @typescript-eslint/no-extra-semi
42
+ ;
43
+ ({ bridge, governance, bank, vault, tbtc } = await hardhat_1.waffle.loadFixture(fixture));
44
+ const accounts = await (0, hardhat_1.getUnnamedAccounts)();
45
+ account1 = await hardhat_1.ethers.getSigner(accounts[0]);
46
+ account2 = await hardhat_1.ethers.getSigner(accounts[1]);
47
+ await bank.connect(bridge).increaseBalance(account1.address, initialBalance);
48
+ await bank.connect(bridge).increaseBalance(account2.address, initialBalance);
49
+ await bank.connect(account1).approveBalance(vault.address, initialBalance);
50
+ await bank.connect(account2).approveBalance(vault.address, initialBalance);
51
+ });
52
+ describe("constructor", () => {
53
+ context("when called with a 0-address bank", () => {
54
+ it("should revert", async () => {
55
+ const TBTCVault = await hardhat_1.ethers.getContractFactory("TBTCVault");
56
+ await (0, chai_1.expect)(TBTCVault.deploy(ZERO_ADDRESS, tbtc.address)).to.be.revertedWith("Bank can not be the zero address");
57
+ });
58
+ });
59
+ context("when called with a 0-address TBTC token", () => {
60
+ it("should revert", async () => {
61
+ const TBTCVault = await hardhat_1.ethers.getContractFactory("TBTCVault");
62
+ await (0, chai_1.expect)(TBTCVault.deploy(bank.address, ZERO_ADDRESS)).to.be.revertedWith("TBTC token can not be the zero address");
63
+ });
64
+ });
65
+ context("when called with correct parameters", () => {
66
+ it("should set the Bank field", async () => {
67
+ (0, chai_1.expect)(await vault.bank()).to.equal(bank.address);
68
+ });
69
+ it("should set the TBTC token field", async () => {
70
+ (0, chai_1.expect)(await vault.tbtcToken()).to.equal(tbtc.address);
71
+ });
72
+ });
73
+ });
74
+ describe("recoverERC20FromToken", () => {
75
+ let testToken;
76
+ before(async () => {
77
+ await createSnapshot();
78
+ const TestToken = await hardhat_1.ethers.getContractFactory("TestERC20");
79
+ testToken = await TestToken.deploy();
80
+ await testToken.deployed();
81
+ });
82
+ after(async () => {
83
+ await restoreSnapshot();
84
+ });
85
+ context("when called not by the governance", () => {
86
+ it("should revert", async () => {
87
+ await (0, chai_1.expect)(vault.recoverERC20FromToken(testToken.address, account1.address, to1e18(800))).to.be.revertedWith("Ownable: caller is not the owner");
88
+ });
89
+ });
90
+ context("when called with correct parameters", () => {
91
+ before(async () => {
92
+ await createSnapshot();
93
+ // Do the misfund.
94
+ await testToken.mint(account1.address, to1e18(1000));
95
+ await testToken.connect(account1).transfer(tbtc.address, to1e18(1000));
96
+ await vault
97
+ .connect(governance)
98
+ .recoverERC20FromToken(testToken.address, account1.address, to1e18(800));
99
+ });
100
+ after(async () => {
101
+ await restoreSnapshot();
102
+ });
103
+ it("should do a successful recovery", async () => {
104
+ (0, chai_1.expect)(await testToken.balanceOf(account1.address)).to.be.equal(to1e18(800));
105
+ (0, chai_1.expect)(await testToken.balanceOf(tbtc.address)).to.be.equal(to1e18(200));
106
+ });
107
+ });
108
+ });
109
+ describe("recoverERC721FromToken", () => {
110
+ let testToken;
111
+ before(async () => {
112
+ await createSnapshot();
113
+ const TestToken = await hardhat_1.ethers.getContractFactory("TestERC721");
114
+ testToken = await TestToken.deploy();
115
+ await testToken.deployed();
116
+ });
117
+ after(async () => {
118
+ await restoreSnapshot();
119
+ });
120
+ context("when called not by the governance", () => {
121
+ it("should revert", async () => {
122
+ await (0, chai_1.expect)(vault.recoverERC721FromToken(testToken.address, account1.address, 1, "0x01")).to.be.revertedWith("Ownable: caller is not the owner");
123
+ });
124
+ });
125
+ context("when called with correct parameters", () => {
126
+ before(async () => {
127
+ await createSnapshot();
128
+ await testToken.mint(account1.address, 1);
129
+ await testToken
130
+ .connect(account1)
131
+ .transferFrom(account1.address, tbtc.address, 1);
132
+ await vault
133
+ .connect(governance)
134
+ .recoverERC721FromToken(testToken.address, account1.address, 1, "0x01");
135
+ });
136
+ after(async () => {
137
+ await restoreSnapshot();
138
+ });
139
+ it("should do a successful recovery", async () => {
140
+ (0, chai_1.expect)(await testToken.ownerOf(1)).to.be.equal(account1.address);
141
+ });
142
+ });
143
+ });
144
+ describe("recoverERC20", () => {
145
+ let testToken;
146
+ before(async () => {
147
+ await createSnapshot();
148
+ const TestToken = await hardhat_1.ethers.getContractFactory("TestERC20");
149
+ testToken = await TestToken.deploy();
150
+ await testToken.deployed();
151
+ });
152
+ after(async () => {
153
+ await restoreSnapshot();
154
+ });
155
+ context("when called not by the governance", () => {
156
+ it("should revert", async () => {
157
+ await (0, chai_1.expect)(vault.recoverERC20(testToken.address, account1.address, to1e18(800))).to.be.revertedWith("Ownable: caller is not the owner");
158
+ });
159
+ });
160
+ context("when called with correct parameters", () => {
161
+ before(async () => {
162
+ await createSnapshot();
163
+ await testToken.mint(account1.address, to1e18(1000));
164
+ await testToken.connect(account1).transfer(vault.address, to1e18(1000));
165
+ await vault
166
+ .connect(governance)
167
+ .recoverERC20(testToken.address, account1.address, to1e18(800));
168
+ });
169
+ after(async () => {
170
+ await restoreSnapshot();
171
+ });
172
+ it("should do a successful recovery", async () => {
173
+ (0, chai_1.expect)(await testToken.balanceOf(account1.address)).to.be.equal(to1e18(800));
174
+ (0, chai_1.expect)(await testToken.balanceOf(vault.address)).to.be.equal(to1e18(200));
175
+ });
176
+ });
177
+ });
178
+ describe("recoverERC721", () => {
179
+ let testToken;
180
+ before(async () => {
181
+ await createSnapshot();
182
+ const TestToken = await hardhat_1.ethers.getContractFactory("TestERC721");
183
+ testToken = await TestToken.deploy();
184
+ await testToken.deployed();
185
+ });
186
+ after(async () => {
187
+ await restoreSnapshot();
188
+ });
189
+ context("when called not by the governance", () => {
190
+ it("should revert", async () => {
191
+ await (0, chai_1.expect)(vault.recoverERC721(testToken.address, account1.address, 1, [])).to.be.revertedWith("Ownable: caller is not the owner");
192
+ });
193
+ });
194
+ context("when called with correct parameters", () => {
195
+ before(async () => {
196
+ await createSnapshot();
197
+ await testToken.mint(account1.address, 1);
198
+ await testToken
199
+ .connect(account1)
200
+ .transferFrom(account1.address, vault.address, 1);
201
+ await vault
202
+ .connect(governance)
203
+ .recoverERC721(testToken.address, account1.address, 1, []);
204
+ });
205
+ after(async () => {
206
+ await restoreSnapshot();
207
+ });
208
+ it("should do a successful recovery", async () => {
209
+ (0, chai_1.expect)(await testToken.ownerOf(1)).to.be.equal(account1.address);
210
+ });
211
+ });
212
+ });
213
+ describe("mint", () => {
214
+ context("when minter has not enough balance in the bank", () => {
215
+ const amount = initialBalance.add(1);
216
+ before(async () => {
217
+ await createSnapshot();
218
+ await bank.connect(account1).approveBalance(vault.address, amount);
219
+ });
220
+ after(async () => {
221
+ await restoreSnapshot();
222
+ });
223
+ it("should revert", async () => {
224
+ await (0, chai_1.expect)(vault.connect(account1).mint(amount)).to.be.revertedWith("Amount exceeds balance in the bank");
225
+ });
226
+ });
227
+ context("when there is a single minter", () => {
228
+ const amount = to1e18(13); // 3 + 1 + 9 = 13
229
+ const transactions = [];
230
+ before(async () => {
231
+ await createSnapshot();
232
+ transactions.push(await vault.connect(account1).mint(to1e18(3)));
233
+ transactions.push(await vault.connect(account1).mint(to1e18(1)));
234
+ transactions.push(await vault.connect(account1).mint(to1e18(9)));
235
+ });
236
+ after(async () => {
237
+ await restoreSnapshot();
238
+ });
239
+ it("should transfer balance to the vault", async () => {
240
+ (0, chai_1.expect)(await bank.balanceOf(vault.address)).to.equal(amount);
241
+ (0, chai_1.expect)(await bank.balanceOf(account1.address)).to.equal(initialBalance.sub(amount));
242
+ });
243
+ it("should mint TBTC", async () => {
244
+ (0, chai_1.expect)(await tbtc.balanceOf(account1.address)).to.equal(amount);
245
+ (0, chai_1.expect)(await tbtc.totalSupply()).to.equal(amount);
246
+ });
247
+ it("should emit Minted event", async () => {
248
+ await (0, chai_1.expect)(transactions[0])
249
+ .to.emit(vault, "Minted")
250
+ .withArgs(account1.address, to1e18(3));
251
+ await (0, chai_1.expect)(transactions[1])
252
+ .to.emit(vault, "Minted")
253
+ .withArgs(account1.address, to1e18(1));
254
+ await (0, chai_1.expect)(transactions[2])
255
+ .to.emit(vault, "Minted")
256
+ .withArgs(account1.address, to1e18(9));
257
+ });
258
+ });
259
+ context("when there are multiple minters", () => {
260
+ const amount1 = to1e18(13); // 3 + 1 + 9 = 13
261
+ const amount2 = to1e18(3); // 1 + 2 = 3
262
+ const transactions = [];
263
+ before(async () => {
264
+ await createSnapshot();
265
+ transactions.push(await vault.connect(account1).mint(to1e18(3)));
266
+ transactions.push(await vault.connect(account2).mint(to1e18(1)));
267
+ transactions.push(await vault.connect(account1).mint(to1e18(1)));
268
+ transactions.push(await vault.connect(account1).mint(to1e18(9)));
269
+ transactions.push(await vault.connect(account2).mint(to1e18(2)));
270
+ });
271
+ after(async () => {
272
+ await restoreSnapshot();
273
+ });
274
+ it("should transfer balances to the vault", async () => {
275
+ (0, chai_1.expect)(await bank.balanceOf(vault.address)).to.equal(amount1.add(amount2));
276
+ (0, chai_1.expect)(await bank.balanceOf(account1.address)).to.equal(initialBalance.sub(amount1));
277
+ (0, chai_1.expect)(await bank.balanceOf(account2.address)).to.equal(initialBalance.sub(amount2));
278
+ });
279
+ it("should mint TBTC", async () => {
280
+ (0, chai_1.expect)(await tbtc.balanceOf(account1.address)).to.equal(amount1);
281
+ (0, chai_1.expect)(await tbtc.balanceOf(account2.address)).to.equal(amount2);
282
+ (0, chai_1.expect)(await tbtc.totalSupply()).to.equal(amount1.add(amount2));
283
+ });
284
+ it("should emit Minted event", async () => {
285
+ await (0, chai_1.expect)(transactions[0])
286
+ .to.emit(vault, "Minted")
287
+ .withArgs(account1.address, to1e18(3));
288
+ await (0, chai_1.expect)(transactions[1])
289
+ .to.emit(vault, "Minted")
290
+ .withArgs(account2.address, to1e18(1));
291
+ await (0, chai_1.expect)(transactions[2])
292
+ .to.emit(vault, "Minted")
293
+ .withArgs(account1.address, to1e18(1));
294
+ await (0, chai_1.expect)(transactions[3])
295
+ .to.emit(vault, "Minted")
296
+ .withArgs(account1.address, to1e18(9));
297
+ await (0, chai_1.expect)(transactions[4])
298
+ .to.emit(vault, "Minted")
299
+ .withArgs(account2.address, to1e18(2));
300
+ });
301
+ });
302
+ });
303
+ describe("unmint", () => {
304
+ context("when the unminter has no TBTC", () => {
305
+ const amount = to1e18(1);
306
+ before(async () => {
307
+ await createSnapshot();
308
+ await tbtc.connect(account1).approve(vault.address, amount);
309
+ });
310
+ after(async () => {
311
+ await restoreSnapshot();
312
+ });
313
+ it("should revert", async () => {
314
+ await (0, chai_1.expect)(vault.connect(account1).unmint(to1e18(1))).to.be.revertedWith("Burn amount exceeds balance");
315
+ });
316
+ });
317
+ context("when the unminter has not enough TBTC", () => {
318
+ const mintedAmount = to1e18(1);
319
+ const unmintedAmount = mintedAmount.add(1);
320
+ before(async () => {
321
+ await createSnapshot();
322
+ await vault.connect(account1).mint(mintedAmount);
323
+ await tbtc.connect(account1).approve(vault.address, unmintedAmount);
324
+ });
325
+ after(async () => {
326
+ await restoreSnapshot();
327
+ });
328
+ it("should revert", async () => {
329
+ await (0, chai_1.expect)(vault.connect(account1).unmint(unmintedAmount)).to.be.revertedWith("Burn amount exceeds balance");
330
+ });
331
+ });
332
+ context("when there is a single unminter", () => {
333
+ const mintedAmount = to1e18(20);
334
+ const unmintedAmount = to1e18(12); // 1 + 3 + 8 = 12
335
+ const notUnmintedAmount = mintedAmount.sub(unmintedAmount);
336
+ const transactions = [];
337
+ before(async () => {
338
+ await createSnapshot();
339
+ await vault.connect(account1).mint(mintedAmount);
340
+ await tbtc.connect(account1).approve(vault.address, unmintedAmount);
341
+ transactions.push(await vault.connect(account1).unmint(to1e18(1)));
342
+ transactions.push(await vault.connect(account1).unmint(to1e18(3)));
343
+ transactions.push(await vault.connect(account1).unmint(to1e18(8)));
344
+ });
345
+ after(async () => {
346
+ await restoreSnapshot();
347
+ });
348
+ it("should transfer balance to the unminter", async () => {
349
+ (0, chai_1.expect)(await bank.balanceOf(vault.address)).to.equal(notUnmintedAmount);
350
+ (0, chai_1.expect)(await bank.balanceOf(account1.address)).to.equal(initialBalance.sub(notUnmintedAmount));
351
+ });
352
+ it("should burn TBTC", async () => {
353
+ (0, chai_1.expect)(await tbtc.balanceOf(account1.address)).to.equal(notUnmintedAmount);
354
+ (0, chai_1.expect)(await tbtc.totalSupply()).to.be.equal(notUnmintedAmount);
355
+ });
356
+ it("should emit Unminted events", async () => {
357
+ await (0, chai_1.expect)(transactions[0])
358
+ .to.emit(vault, "Unminted")
359
+ .withArgs(account1.address, to1e18(1));
360
+ await (0, chai_1.expect)(transactions[1])
361
+ .to.emit(vault, "Unminted")
362
+ .withArgs(account1.address, to1e18(3));
363
+ await (0, chai_1.expect)(transactions[2])
364
+ .to.emit(vault, "Unminted")
365
+ .withArgs(account1.address, to1e18(8));
366
+ });
367
+ });
368
+ context("when there are multiple unminters", () => {
369
+ const mintedAmount1 = to1e18(20);
370
+ const unmintedAmount1 = to1e18(12); // 1 + 3 + 8 = 12
371
+ const notUnmintedAmount1 = mintedAmount1.sub(unmintedAmount1);
372
+ const mintedAmount2 = to1e18(41);
373
+ const unmintedAmount2 = to1e18(30); // 20 + 10 = 30
374
+ const notUnmintedAmount2 = mintedAmount2.sub(unmintedAmount2);
375
+ const transactions = [];
376
+ before(async () => {
377
+ await createSnapshot();
378
+ await vault.connect(account1).mint(mintedAmount1);
379
+ await vault.connect(account2).mint(mintedAmount2);
380
+ await tbtc.connect(account1).approve(vault.address, unmintedAmount1);
381
+ await tbtc.connect(account2).approve(vault.address, unmintedAmount2);
382
+ transactions.push(await vault.connect(account1).unmint(to1e18(1)));
383
+ transactions.push(await vault.connect(account2).unmint(to1e18(20)));
384
+ transactions.push(await vault.connect(account1).unmint(to1e18(3)));
385
+ transactions.push(await vault.connect(account1).unmint(to1e18(8)));
386
+ transactions.push(await vault.connect(account2).unmint(to1e18(10)));
387
+ });
388
+ after(async () => {
389
+ await restoreSnapshot();
390
+ });
391
+ it("should transfer balances to unminters", async () => {
392
+ (0, chai_1.expect)(await bank.balanceOf(vault.address)).to.equal(notUnmintedAmount1.add(notUnmintedAmount2));
393
+ (0, chai_1.expect)(await bank.balanceOf(account1.address)).to.equal(initialBalance.sub(notUnmintedAmount1));
394
+ (0, chai_1.expect)(await bank.balanceOf(account2.address)).to.equal(initialBalance.sub(notUnmintedAmount2));
395
+ });
396
+ it("should burn TBTC", async () => {
397
+ (0, chai_1.expect)(await tbtc.balanceOf(account1.address)).to.equal(notUnmintedAmount1);
398
+ (0, chai_1.expect)(await tbtc.balanceOf(account2.address)).to.equal(notUnmintedAmount2);
399
+ (0, chai_1.expect)(await tbtc.totalSupply()).to.be.equal(notUnmintedAmount1.add(notUnmintedAmount2));
400
+ });
401
+ it("should emit Unminted events", async () => {
402
+ await (0, chai_1.expect)(transactions[0])
403
+ .to.emit(vault, "Unminted")
404
+ .withArgs(account1.address, to1e18(1));
405
+ await (0, chai_1.expect)(transactions[1])
406
+ .to.emit(vault, "Unminted")
407
+ .withArgs(account2.address, to1e18(20));
408
+ await (0, chai_1.expect)(transactions[2])
409
+ .to.emit(vault, "Unminted")
410
+ .withArgs(account1.address, to1e18(3));
411
+ await (0, chai_1.expect)(transactions[3])
412
+ .to.emit(vault, "Unminted")
413
+ .withArgs(account1.address, to1e18(8));
414
+ await (0, chai_1.expect)(transactions[4])
415
+ .to.emit(vault, "Unminted")
416
+ .withArgs(account2.address, to1e18(10));
417
+ });
418
+ });
419
+ });
420
+ describe("receiveApproval", () => {
421
+ context("when called not for TBTC token", () => {
422
+ it("should revert", async () => {
423
+ await (0, chai_1.expect)(vault
424
+ .connect(account1)
425
+ .receiveApproval(account1.address, to1e18(1), account1.address, [])).to.be.revertedWith("Token is not TBTC");
426
+ });
427
+ });
428
+ context("when called directly", () => {
429
+ it("should revert", async () => {
430
+ await (0, chai_1.expect)(vault
431
+ .connect(account1)
432
+ .receiveApproval(account1.address, to1e18(1), tbtc.address, [])).to.be.revertedWith("Only TBTC caller allowed");
433
+ });
434
+ });
435
+ context("when called via approveAndCall", () => {
436
+ context("when called with an empty extraData", () => {
437
+ const mintedAmount = to1e18(10);
438
+ const unmintedAmount = to1e18(4);
439
+ const notUnmintedAmount = mintedAmount.sub(unmintedAmount);
440
+ let tx;
441
+ before(async () => {
442
+ await createSnapshot();
443
+ await vault.connect(account1).mint(mintedAmount);
444
+ tx = await tbtc
445
+ .connect(account1)
446
+ .approveAndCall(vault.address, unmintedAmount, []);
447
+ });
448
+ after(async () => {
449
+ await restoreSnapshot();
450
+ });
451
+ it("should transfer balance to the unminter", async () => {
452
+ (0, chai_1.expect)(await bank.balanceOf(vault.address)).to.equal(notUnmintedAmount);
453
+ (0, chai_1.expect)(await bank.balanceOf(account1.address)).to.equal(initialBalance.sub(notUnmintedAmount));
454
+ });
455
+ it("should burn TBTC", async () => {
456
+ (0, chai_1.expect)(await tbtc.balanceOf(account1.address)).to.equal(notUnmintedAmount);
457
+ (0, chai_1.expect)(await tbtc.totalSupply()).to.be.equal(notUnmintedAmount);
458
+ });
459
+ it("should emit Unminted event", async () => {
460
+ await (0, chai_1.expect)(tx)
461
+ .to.emit(vault, "Unminted")
462
+ .withArgs(account1.address, unmintedAmount);
463
+ });
464
+ });
465
+ });
466
+ });
467
+ describe("receiveBalanceApproval", () => {
468
+ context("when called not by the bank", () => {
469
+ const amount = initialBalance;
470
+ it("should revert", async () => {
471
+ await (0, chai_1.expect)(vault
472
+ .connect(bridge)
473
+ .receiveBalanceApproval(account1.address, amount, [])).to.be.revertedWith("Caller is not the Bank");
474
+ await (0, chai_1.expect)(vault
475
+ .connect(account1)
476
+ .receiveBalanceApproval(account1.address, amount, [])).to.be.revertedWith("Caller is not the Bank");
477
+ });
478
+ });
479
+ context("when caller has not enough balance in the bank", () => {
480
+ const amount = initialBalance.add(1);
481
+ it("should revert", async () => {
482
+ await (0, chai_1.expect)(bank
483
+ .connect(account1)
484
+ .approveBalanceAndCall(vault.address, amount, [])).to.be.revertedWith("Amount exceeds balance in the bank");
485
+ });
486
+ });
487
+ context("when there is a single caller", () => {
488
+ const amount = to1e18(19); // 4 + 10 + 5
489
+ const transactions = [];
490
+ before(async () => {
491
+ await createSnapshot();
492
+ transactions.push(await bank
493
+ .connect(account1)
494
+ .approveBalanceAndCall(vault.address, to1e18(4), []));
495
+ transactions.push(await bank
496
+ .connect(account1)
497
+ .approveBalanceAndCall(vault.address, to1e18(10), []));
498
+ transactions.push(await bank
499
+ .connect(account1)
500
+ .approveBalanceAndCall(vault.address, to1e18(5), []));
501
+ });
502
+ after(async () => {
503
+ await restoreSnapshot();
504
+ });
505
+ it("should transfer balance to the vault", async () => {
506
+ (0, chai_1.expect)(await bank.balanceOf(vault.address)).to.equal(amount);
507
+ (0, chai_1.expect)(await bank.balanceOf(account1.address)).to.equal(initialBalance.sub(amount));
508
+ });
509
+ it("should mint TBTC", async () => {
510
+ (0, chai_1.expect)(await tbtc.balanceOf(account1.address)).to.equal(amount);
511
+ (0, chai_1.expect)(await tbtc.totalSupply()).to.equal(amount);
512
+ });
513
+ it("should emit Minted event", async () => {
514
+ await (0, chai_1.expect)(transactions[0])
515
+ .to.emit(vault, "Minted")
516
+ .withArgs(account1.address, to1e18(4));
517
+ await (0, chai_1.expect)(transactions[1])
518
+ .to.emit(vault, "Minted")
519
+ .withArgs(account1.address, to1e18(10));
520
+ await (0, chai_1.expect)(transactions[2])
521
+ .to.emit(vault, "Minted")
522
+ .withArgs(account1.address, to1e18(5));
523
+ });
524
+ });
525
+ context("when there are multiple callers", () => {
526
+ const amount1 = to1e18(4); // 2 + 1 + 1 = 4
527
+ const amount2 = to1e18(5); // 4 + 1 = 5
528
+ const transactions = [];
529
+ before(async () => {
530
+ await createSnapshot();
531
+ transactions.push(await bank
532
+ .connect(account1)
533
+ .approveBalanceAndCall(vault.address, to1e18(2), []));
534
+ transactions.push(await bank
535
+ .connect(account2)
536
+ .approveBalanceAndCall(vault.address, to1e18(4), []));
537
+ transactions.push(await bank
538
+ .connect(account1)
539
+ .approveBalanceAndCall(vault.address, to1e18(1), []));
540
+ transactions.push(await bank
541
+ .connect(account1)
542
+ .approveBalanceAndCall(vault.address, to1e18(1), []));
543
+ transactions.push(await bank
544
+ .connect(account2)
545
+ .approveBalanceAndCall(vault.address, to1e18(1), []));
546
+ });
547
+ after(async () => {
548
+ await restoreSnapshot();
549
+ });
550
+ it("should transfer balances to the vault", async () => {
551
+ (0, chai_1.expect)(await bank.balanceOf(vault.address)).to.equal(amount1.add(amount2));
552
+ (0, chai_1.expect)(await bank.balanceOf(account1.address)).to.equal(initialBalance.sub(amount1));
553
+ (0, chai_1.expect)(await bank.balanceOf(account2.address)).to.equal(initialBalance.sub(amount2));
554
+ });
555
+ it("should mint TBTC", async () => {
556
+ (0, chai_1.expect)(await tbtc.balanceOf(account1.address)).to.equal(amount1);
557
+ (0, chai_1.expect)(await tbtc.balanceOf(account2.address)).to.equal(amount2);
558
+ (0, chai_1.expect)(await tbtc.totalSupply()).to.equal(amount1.add(amount2));
559
+ });
560
+ it("should emit Minted event", async () => {
561
+ await (0, chai_1.expect)(transactions[0])
562
+ .to.emit(vault, "Minted")
563
+ .withArgs(account1.address, to1e18(2));
564
+ await (0, chai_1.expect)(transactions[1])
565
+ .to.emit(vault, "Minted")
566
+ .withArgs(account2.address, to1e18(4));
567
+ await (0, chai_1.expect)(transactions[2])
568
+ .to.emit(vault, "Minted")
569
+ .withArgs(account1.address, to1e18(1));
570
+ await (0, chai_1.expect)(transactions[3])
571
+ .to.emit(vault, "Minted")
572
+ .withArgs(account1.address, to1e18(1));
573
+ await (0, chai_1.expect)(transactions[4])
574
+ .to.emit(vault, "Minted")
575
+ .withArgs(account2.address, to1e18(1));
576
+ });
577
+ });
578
+ });
579
+ describe("receiveBalanceIncrease", () => {
580
+ const depositor1 = "0x30c371E0651B2Ff6062158ca1D95b07C7531c719";
581
+ const depositor2 = "0xb3464806d680722dBc678996F1670D19A42eA3e9";
582
+ const depositor3 = "0x6B9925e04bc46569d1F7362eD7f11539234f0aEc";
583
+ const depositedAmount1 = to1e18(19);
584
+ const depositedAmount2 = to1e18(11);
585
+ const depositedAmount3 = to1e18(301);
586
+ const totalDepositedAmount = to1e18(331); // 19 + 11 + 301
587
+ before(async () => {
588
+ await createSnapshot();
589
+ });
590
+ after(async () => {
591
+ await restoreSnapshot();
592
+ });
593
+ context("when called not by the bank", () => {
594
+ it("should revert", async () => {
595
+ await (0, chai_1.expect)(vault
596
+ .connect(bridge)
597
+ .receiveBalanceIncrease([depositor1], [depositedAmount1])).to.be.revertedWith("Caller is not the Bank");
598
+ });
599
+ });
600
+ context("when called with no depositors", () => {
601
+ it("should revert", async () => {
602
+ await (0, chai_1.expect)(bank.connect(bridge).increaseBalanceAndCall(vault.address, [], [])).to.be.revertedWith("No depositors specified");
603
+ });
604
+ });
605
+ context("with single depositor", () => {
606
+ let tx;
607
+ before(async () => {
608
+ await createSnapshot();
609
+ tx = await bank
610
+ .connect(bridge)
611
+ .increaseBalanceAndCall(vault.address, [depositor1], [depositedAmount1]);
612
+ });
613
+ after(async () => {
614
+ await restoreSnapshot();
615
+ });
616
+ it("should mint TBTC", async () => {
617
+ (0, chai_1.expect)(await tbtc.balanceOf(depositor1)).to.equal(depositedAmount1);
618
+ (0, chai_1.expect)(await tbtc.totalSupply()).to.equal(depositedAmount1);
619
+ });
620
+ it("should emit Minted event", async () => {
621
+ await (0, chai_1.expect)(tx)
622
+ .to.emit(vault, "Minted")
623
+ .withArgs(depositor1, depositedAmount1);
624
+ });
625
+ });
626
+ context("with multiple depositors", () => {
627
+ let tx;
628
+ before(async () => {
629
+ await createSnapshot();
630
+ tx = await bank
631
+ .connect(bridge)
632
+ .increaseBalanceAndCall(vault.address, [depositor1, depositor2, depositor3], [depositedAmount1, depositedAmount2, depositedAmount3]);
633
+ });
634
+ after(async () => {
635
+ await restoreSnapshot();
636
+ });
637
+ it("should mint TBTC", async () => {
638
+ (0, chai_1.expect)(await tbtc.balanceOf(depositor1)).to.equal(depositedAmount1);
639
+ (0, chai_1.expect)(await tbtc.balanceOf(depositor2)).to.equal(depositedAmount2);
640
+ (0, chai_1.expect)(await tbtc.balanceOf(depositor3)).to.equal(depositedAmount3);
641
+ (0, chai_1.expect)(await tbtc.totalSupply()).to.equal(totalDepositedAmount);
642
+ });
643
+ it("should emit Minted events", async () => {
644
+ await (0, chai_1.expect)(tx)
645
+ .to.emit(vault, "Minted")
646
+ .withArgs(depositor1, depositedAmount1);
647
+ await (0, chai_1.expect)(tx)
648
+ .to.emit(vault, "Minted")
649
+ .withArgs(depositor2, depositedAmount2);
650
+ await (0, chai_1.expect)(tx)
651
+ .to.emit(vault, "Minted")
652
+ .withArgs(depositor3, depositedAmount3);
653
+ });
654
+ });
655
+ });
656
+ describe("initiateUpgrade", () => {
657
+ const newVault = "0xE4d1514C79ae3967f4410Aaf861Bb59307b243a3";
658
+ context("when called not by the governance", () => {
659
+ it("should revert", async () => {
660
+ await (0, chai_1.expect)(vault.connect(account1).initiateUpgrade(newVault)).to.be.revertedWith("Ownable: caller is not the owner");
661
+ });
662
+ });
663
+ context("when called by the governance", () => {
664
+ context("when called with a zero-address new vault", () => {
665
+ it("should revert", async () => {
666
+ await (0, chai_1.expect)(vault.connect(governance).initiateUpgrade(ZERO_ADDRESS)).to.be.revertedWith("New vault address cannot be zero");
667
+ });
668
+ });
669
+ context("when called with a non-zero-address new vault", () => {
670
+ let tx;
671
+ before(async () => {
672
+ await createSnapshot();
673
+ tx = await vault.connect(governance).initiateUpgrade(newVault);
674
+ });
675
+ after(async () => {
676
+ await restoreSnapshot();
677
+ });
678
+ it("should not transfer TBTC token ownership", async () => {
679
+ (0, chai_1.expect)(await tbtc.owner()).is.equal(vault.address);
680
+ });
681
+ it("should set the upgrade initiation time", async () => {
682
+ (0, chai_1.expect)(await vault.upgradeInitiatedTimestamp()).to.equal(await lastBlockTime());
683
+ });
684
+ it("should set the new vault address", async () => {
685
+ (0, chai_1.expect)(await vault.newVault()).to.equal(newVault);
686
+ });
687
+ it("should emit UpgradeInitiated event", async () => {
688
+ await (0, chai_1.expect)(tx)
689
+ .to.emit(vault, "UpgradeInitiated")
690
+ .withArgs(newVault, await lastBlockTime());
691
+ });
692
+ });
693
+ });
694
+ });
695
+ describe("finalizeUpgrade", () => {
696
+ context("when called not by the governance", () => {
697
+ it("should revert", async () => {
698
+ await (0, chai_1.expect)(vault.connect(account1).finalizeUpgrade()).to.be.revertedWith("Ownable: caller is not the owner");
699
+ });
700
+ });
701
+ context("when called by the governance", () => {
702
+ context("when the upgrade process has not been initiated", () => {
703
+ it("should revert", async () => {
704
+ await (0, chai_1.expect)(vault.connect(governance).finalizeUpgrade()).to.be.revertedWith("Change not initiated");
705
+ });
706
+ });
707
+ context("when the upgrade process has been initiated", () => {
708
+ const newVault = "0x8C338c4222082bdFA5FeC478747Bb1e102A264D9";
709
+ before(async () => {
710
+ await createSnapshot();
711
+ await vault.connect(governance).initiateUpgrade(newVault);
712
+ // Mint some TBTC to increase the balance of TBTCVault
713
+ await bank
714
+ .connect(account1)
715
+ .approveBalanceAndCall(vault.address, initialBalance, []);
716
+ await bank
717
+ .connect(account2)
718
+ .approveBalanceAndCall(vault.address, initialBalance, []);
719
+ });
720
+ after(async () => {
721
+ await restoreSnapshot();
722
+ });
723
+ context("when the governance delay has not passed", () => {
724
+ before(async () => {
725
+ await createSnapshot();
726
+ await increaseTime(86400 - 60); // 24h - 1min
727
+ });
728
+ after(async () => {
729
+ await restoreSnapshot();
730
+ });
731
+ it("should revert", async () => {
732
+ await (0, chai_1.expect)(vault.connect(governance).finalizeUpgrade()).to.be.revertedWith("Governance delay has not elapsed");
733
+ });
734
+ });
735
+ context("when the governance delay passed", () => {
736
+ let tx;
737
+ before(async () => {
738
+ await createSnapshot();
739
+ await increaseTime(86400); // 24h
740
+ tx = await vault.connect(governance).finalizeUpgrade();
741
+ });
742
+ after(async () => {
743
+ await restoreSnapshot();
744
+ });
745
+ it("should transfer TBTC token ownership", async () => {
746
+ (0, chai_1.expect)(await tbtc.owner()).is.equal(newVault);
747
+ });
748
+ it("should transfer the entire bank balance", async () => {
749
+ (0, chai_1.expect)(await bank.balanceOf(vault.address)).to.equal(0);
750
+ // In the setup, each account minted `initialBalance` of TBTC.
751
+ (0, chai_1.expect)(await bank.balanceOf(newVault)).to.equal(initialBalance.mul(2));
752
+ });
753
+ it("should emit UpgradeFinalized event", async () => {
754
+ await (0, chai_1.expect)(tx)
755
+ .to.emit(vault, "UpgradeFinalized")
756
+ .withArgs(newVault);
757
+ });
758
+ it("should reset the upgrade initiation time", async () => {
759
+ (0, chai_1.expect)(await vault.upgradeInitiatedTimestamp()).to.equal(0);
760
+ });
761
+ it("should reset the new vault address", async () => {
762
+ (0, chai_1.expect)(await vault.newVault()).to.equal(ZERO_ADDRESS);
763
+ });
764
+ });
765
+ });
766
+ });
767
+ });
768
+ });