@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.
- package/README.adoc +12 -0
- package/artifacts/.chainId +1 -1
- package/artifacts/Bank.json +807 -0
- package/artifacts/Bridge.json +2300 -0
- package/artifacts/Deposit.json +117 -0
- package/artifacts/DepositSweep.json +77 -0
- package/artifacts/EcdsaDkgValidator.json +532 -0
- package/artifacts/EcdsaInactivity.json +156 -0
- package/artifacts/EcdsaSortitionPool.json +1004 -0
- package/artifacts/Fraud.json +164 -0
- package/artifacts/KeepRegistry.json +99 -0
- package/artifacts/KeepStake.json +286 -0
- package/artifacts/KeepToken.json +711 -0
- package/artifacts/KeepTokenStaking.json +483 -0
- package/artifacts/MovingFunds.json +249 -0
- package/artifacts/NuCypherStakingEscrow.json +256 -0
- package/artifacts/NuCypherToken.json +711 -0
- package/artifacts/RandomBeaconStub.json +141 -0
- package/artifacts/Redemption.json +174 -0
- package/artifacts/ReimbursementPool.json +509 -0
- package/artifacts/Relay.json +123 -0
- package/artifacts/T.json +1148 -0
- package/artifacts/TBTC.json +36 -35
- package/artifacts/TBTCToken.json +738 -0
- package/artifacts/TBTCVault.json +691 -0
- package/artifacts/TokenStaking.json +2288 -0
- package/artifacts/TokenholderGovernor.json +1795 -0
- package/artifacts/TokenholderTimelock.json +1058 -0
- package/artifacts/VendingMachine.json +34 -33
- package/artifacts/VendingMachineKeep.json +400 -0
- package/artifacts/VendingMachineNuCypher.json +400 -0
- package/artifacts/WalletRegistry.json +1843 -0
- package/artifacts/WalletRegistryGovernance.json +2754 -0
- package/artifacts/Wallets.json +186 -0
- package/artifacts/solcInputs/5e62cff1ead0900b07facca4b559e818.json +314 -0
- package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
- package/build/contracts/GovernanceUtils.sol/GovernanceUtils.json +2 -2
- package/build/contracts/bank/Bank.sol/Bank.dbg.json +4 -0
- package/build/contracts/bank/Bank.sol/Bank.json +542 -0
- package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.dbg.json +4 -0
- package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.json +34 -0
- package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +4 -0
- package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +10 -0
- package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +4 -0
- package/build/contracts/bridge/Bridge.sol/Bridge.json +2686 -0
- package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +4 -0
- package/build/contracts/bridge/BridgeState.sol/BridgeState.json +226 -0
- package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +4 -0
- package/build/contracts/bridge/Deposit.sol/Deposit.json +72 -0
- package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +4 -0
- package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +30 -0
- package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +4 -0
- package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.json +10 -0
- package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +4 -0
- package/build/contracts/bridge/Fraud.sol/Fraud.json +86 -0
- package/build/contracts/bridge/Heartbeat.sol/Heartbeat.dbg.json +4 -0
- package/build/contracts/bridge/Heartbeat.sol/Heartbeat.json +10 -0
- package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +4 -0
- package/build/contracts/bridge/IRelay.sol/IRelay.json +37 -0
- package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +4 -0
- package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +138 -0
- package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +4 -0
- package/build/contracts/bridge/Redemption.sol/OutboundTx.json +10 -0
- package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +4 -0
- package/build/contracts/bridge/Redemption.sol/Redemption.json +92 -0
- package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
- package/build/contracts/bridge/VendingMachine.sol/VendingMachine.json +2 -2
- package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +4 -0
- package/build/contracts/bridge/Wallets.sol/Wallets.json +112 -0
- package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
- package/build/contracts/token/TBTC.sol/TBTC.json +4 -4
- package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +4 -0
- package/build/contracts/vault/DonationVault.sol/DonationVault.json +108 -0
- package/build/contracts/vault/IVault.sol/IVault.dbg.json +4 -0
- package/build/contracts/vault/IVault.sol/IVault.json +52 -0
- package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +4 -0
- package/build/contracts/vault/TBTCVault.sol/TBTCVault.json +449 -0
- package/contracts/GovernanceUtils.sol +4 -4
- package/contracts/bank/Bank.sol +436 -0
- package/contracts/bank/IReceiveBalanceApproval.sol +45 -0
- package/contracts/bridge/BitcoinTx.sol +326 -0
- package/contracts/bridge/Bridge.sol +1793 -0
- package/contracts/bridge/BridgeState.sol +739 -0
- package/contracts/bridge/Deposit.sol +269 -0
- package/contracts/bridge/DepositSweep.sol +574 -0
- package/contracts/bridge/EcdsaLib.sol +45 -0
- package/contracts/bridge/Fraud.sol +579 -0
- package/contracts/bridge/Heartbeat.sol +112 -0
- package/contracts/bridge/IRelay.sol +28 -0
- package/contracts/bridge/MovingFunds.sol +1077 -0
- package/contracts/bridge/Redemption.sol +1020 -0
- package/contracts/bridge/VendingMachine.sol +2 -2
- package/contracts/bridge/Wallets.sol +719 -0
- package/contracts/hardhat-dependency-compiler/.hardhat-dependency-compiler +1 -0
- package/contracts/hardhat-dependency-compiler/@keep-network/ecdsa/contracts/WalletRegistry.sol +3 -0
- package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol +3 -0
- package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol +3 -0
- package/contracts/token/TBTC.sol +1 -1
- package/contracts/vault/DonationVault.sol +125 -0
- package/contracts/vault/IVault.sol +44 -0
- package/contracts/vault/TBTCVault.sol +305 -0
- package/deploy/00_resolve_relay.ts +28 -0
- package/deploy/00_resolve_tbtc_v1_token.ts +1 -1
- package/deploy/01_deploy_tbtc_v2_token.ts +8 -1
- package/deploy/02_deploy_vending_machine.ts +7 -0
- package/deploy/{03_transfer_roles.ts → 03_transfer_vending_machine_roles.ts} +1 -1
- package/deploy/04_deploy_bank.ts +27 -0
- package/deploy/05_deploy_bridge.ts +80 -0
- package/deploy/06_deploy_tbtc_vault.ts +30 -0
- package/deploy/07_bank_update_bridge.ts +19 -0
- package/deploy/08_transfer_bank_ownership.ts +15 -0
- package/deploy/09_transfer_tbtc_vault_ownership.ts +15 -0
- package/deploy/10_transfer_bridge_governance.ts +20 -0
- package/deploy/11_initialize_wallet_owner.ts +18 -0
- package/deploy/11_transfer_proxy_admin_ownership.ts +30 -0
- package/deploy/12_deploy_proxy_admin_with_deputy.ts +33 -0
- package/export/deploy/00_resolve_relay.js +24 -0
- package/export/deploy/00_resolve_tbtc_v1_token.js +24 -0
- package/export/deploy/01_deploy_tbtc_v2_token.js +19 -0
- package/export/deploy/02_deploy_vending_machine.js +25 -0
- package/export/deploy/03_transfer_vending_machine_roles.js +19 -0
- package/export/deploy/04_deploy_bank.js +21 -0
- package/export/deploy/05_deploy_bridge.js +69 -0
- package/export/deploy/06_deploy_tbtc_vault.js +24 -0
- package/export/deploy/07_bank_update_bridge.js +13 -0
- package/export/deploy/08_transfer_bank_ownership.js +11 -0
- package/export/deploy/09_transfer_tbtc_vault_ownership.js +11 -0
- package/export/deploy/10_transfer_bridge_governance.js +11 -0
- package/export/deploy/11_initialize_wallet_owner.js +14 -0
- package/export/deploy/11_transfer_proxy_admin_ownership.js +23 -0
- package/export/deploy/12_deploy_proxy_admin_with_deputy.js +22 -0
- package/export/hardhat.config.js +169 -0
- package/export/test/bank/Bank.test.js +1012 -0
- package/export/test/bridge/Bridge.Deployment.test.js +76 -0
- package/export/test/bridge/Bridge.Deposit.test.js +1834 -0
- package/export/test/bridge/Bridge.Frauds.test.js +1349 -0
- package/export/test/bridge/Bridge.MovingFunds.test.js +2437 -0
- package/export/test/bridge/Bridge.Parameters.test.js +400 -0
- package/export/test/bridge/Bridge.Redemption.test.js +2523 -0
- package/export/test/bridge/Bridge.Vaults.test.js +74 -0
- package/export/test/bridge/Bridge.Wallets.test.js +1017 -0
- package/export/test/bridge/EcdsaLib.test.js +46 -0
- package/export/test/bridge/Heartbeat.test.js +77 -0
- package/export/test/bridge/VendingMachine.Upgrade.test.js +160 -0
- package/export/test/bridge/VendingMachine.test.js +762 -0
- package/export/test/data/deposit-sweep.js +655 -0
- package/export/test/data/ecdsa.js +18 -0
- package/export/test/data/fraud.js +158 -0
- package/export/test/data/moving-funds.js +815 -0
- package/export/test/data/redemption.js +1011 -0
- package/export/test/fixtures/bridge.js +54 -0
- package/export/test/fixtures/index.js +57 -0
- package/export/test/helpers/contract-test-helpers.js +18 -0
- package/export/test/integration/Slashing.test.js +279 -0
- package/export/test/integration/WalleCreation.test.js +66 -0
- package/export/test/integration/utils/ecdsa-wallet-registry.js +137 -0
- package/export/test/integration/utils/fixture.js +77 -0
- package/export/test/integration/utils/gas.js +36 -0
- package/export/test/integration/utils/random-beacon.js +26 -0
- package/export/test/integration/utils/staking.js +19 -0
- package/export/test/vault/DonationVault.test.js +202 -0
- package/export/test/vault/TBTCVault.Redemption.test.js +357 -0
- package/export/test/vault/TBTCVault.test.js +768 -0
- package/export/typechain/BTCUtils.js +2 -0
- package/export/typechain/Bank.js +2 -0
- package/export/typechain/BankStub.js +2 -0
- package/export/typechain/Bridge.js +2 -0
- package/export/typechain/BridgeState.js +2 -0
- package/export/typechain/BridgeStub.js +2 -0
- package/export/typechain/Deposit.js +2 -0
- package/export/typechain/DepositSweep.js +2 -0
- package/export/typechain/DonationVault.js +2 -0
- package/export/typechain/ERC165.js +2 -0
- package/export/typechain/ERC1967Proxy.js +2 -0
- package/export/typechain/ERC1967Upgrade.js +2 -0
- package/export/typechain/ERC20WithPermit.js +2 -0
- package/export/typechain/ERC721.js +2 -0
- package/export/typechain/EcdsaAuthorization.js +2 -0
- package/export/typechain/EcdsaDkg.js +2 -0
- package/export/typechain/EcdsaDkgValidator.js +2 -0
- package/export/typechain/EcdsaInactivity.js +2 -0
- package/export/typechain/Fraud.js +2 -0
- package/export/typechain/Governable.js +2 -0
- package/export/typechain/HeartbeatStub.js +2 -0
- package/export/typechain/IApplication.js +2 -0
- package/export/typechain/IApproveAndCall.js +2 -0
- package/export/typechain/IBeacon.js +2 -0
- package/export/typechain/IERC165.js +2 -0
- package/export/typechain/IERC1822Proxiable.js +2 -0
- package/export/typechain/IERC20.js +2 -0
- package/export/typechain/IERC20Metadata.js +2 -0
- package/export/typechain/IERC20WithPermit.js +2 -0
- package/export/typechain/IERC721.js +2 -0
- package/export/typechain/IERC721Metadata.js +2 -0
- package/export/typechain/IERC721Receiver.js +2 -0
- package/export/typechain/IRandomBeacon.js +2 -0
- package/export/typechain/IRandomBeaconConsumer.js +2 -0
- package/export/typechain/IReceiveApproval.js +2 -0
- package/export/typechain/IReceiveBalanceApproval.js +2 -0
- package/export/typechain/IRelay.js +2 -0
- package/export/typechain/IStaking.js +2 -0
- package/export/typechain/IVault.js +2 -0
- package/export/typechain/IWalletOwner.js +2 -0
- package/export/typechain/IWalletRegistry.js +2 -0
- package/export/typechain/Initializable.js +2 -0
- package/export/typechain/MisfundRecovery.js +2 -0
- package/export/typechain/MovingFunds.js +2 -0
- package/export/typechain/Ownable.js +2 -0
- package/export/typechain/Proxy.js +2 -0
- package/export/typechain/ProxyAdmin.js +2 -0
- package/export/typechain/ReceiveApprovalStub.js +2 -0
- package/export/typechain/Redemption.js +2 -0
- package/export/typechain/Reimbursable.js +2 -0
- package/export/typechain/ReimbursementPool.js +2 -0
- package/export/typechain/Rewards.js +2 -0
- package/export/typechain/SortitionPool.js +2 -0
- package/export/typechain/SortitionTree.js +2 -0
- package/export/typechain/TBTC.js +2 -0
- package/export/typechain/TBTCVault.js +2 -0
- package/export/typechain/TestERC20.js +2 -0
- package/export/typechain/TestERC721.js +2 -0
- package/export/typechain/TestEcdsaLib.js +2 -0
- package/export/typechain/TestRelay.js +2 -0
- package/export/typechain/TransparentUpgradeableProxy.js +2 -0
- package/export/typechain/VendingMachine.js +2 -0
- package/export/typechain/WalletRegistry.js +2 -0
- package/export/typechain/Wallets.js +2 -0
- package/export/typechain/common.js +2 -0
- package/export/typechain/factories/BTCUtils__factory.js +94 -0
- package/export/typechain/factories/BankStub__factory.js +586 -0
- package/export/typechain/factories/Bank__factory.js +573 -0
- package/export/typechain/factories/BridgeState__factory.js +257 -0
- package/export/typechain/factories/BridgeStub__factory.js +2912 -0
- package/export/typechain/factories/Bridge__factory.js +2526 -0
- package/export/typechain/factories/DepositSweep__factory.js +61 -0
- package/export/typechain/factories/Deposit__factory.js +103 -0
- package/export/typechain/factories/DonationVault__factory.js +139 -0
- package/export/typechain/factories/ERC165__factory.js +38 -0
- package/export/typechain/factories/ERC1967Proxy__factory.js +111 -0
- package/export/typechain/factories/ERC1967Upgrade__factory.js +64 -0
- package/export/typechain/factories/ERC20WithPermit__factory.js +524 -0
- package/export/typechain/factories/ERC721__factory.js +388 -0
- package/export/typechain/factories/EcdsaAuthorization__factory.js +211 -0
- package/export/typechain/factories/EcdsaDkgValidator__factory.js +441 -0
- package/export/typechain/factories/EcdsaDkg__factory.js +192 -0
- package/export/typechain/factories/EcdsaInactivity__factory.js +134 -0
- package/export/typechain/factories/Fraud__factory.js +117 -0
- package/export/typechain/factories/Governable__factory.js +64 -0
- package/export/typechain/factories/HeartbeatStub__factory.js +61 -0
- package/export/typechain/factories/IApplication__factory.js +152 -0
- package/export/typechain/factories/IApproveAndCall__factory.js +48 -0
- package/export/typechain/factories/IBeacon__factory.js +32 -0
- package/export/typechain/factories/IERC165__factory.js +38 -0
- package/export/typechain/factories/IERC1822Proxiable__factory.js +32 -0
- package/export/typechain/factories/IERC20Metadata__factory.js +241 -0
- package/export/typechain/factories/IERC20WithPermit__factory.js +389 -0
- package/export/typechain/factories/IERC20__factory.js +202 -0
- package/export/typechain/factories/IERC721Metadata__factory.js +349 -0
- package/export/typechain/factories/IERC721Receiver__factory.js +53 -0
- package/export/typechain/factories/IERC721__factory.js +304 -0
- package/export/typechain/factories/IRandomBeaconConsumer__factory.js +37 -0
- package/export/typechain/factories/IRandomBeacon__factory.js +32 -0
- package/export/typechain/factories/IReceiveApproval__factory.js +47 -0
- package/export/typechain/factories/IReceiveBalanceApproval__factory.js +42 -0
- package/export/typechain/factories/IRelay__factory.js +45 -0
- package/export/typechain/factories/IStaking__factory.js +722 -0
- package/export/typechain/factories/IVault__factory.js +60 -0
- package/export/typechain/factories/IWalletOwner__factory.js +65 -0
- package/export/typechain/factories/IWalletRegistry__factory.js +138 -0
- package/export/typechain/factories/Initializable__factory.js +32 -0
- package/export/typechain/factories/MisfundRecovery__factory.js +145 -0
- package/export/typechain/factories/MovingFunds__factory.js +169 -0
- package/export/typechain/factories/Ownable__factory.js +71 -0
- package/export/typechain/factories/ProxyAdmin__factory.js +191 -0
- package/export/typechain/factories/Proxy__factory.js +27 -0
- package/export/typechain/factories/ReceiveApprovalStub__factory.js +127 -0
- package/export/typechain/factories/Redemption__factory.js +123 -0
- package/export/typechain/factories/Reimbursable__factory.js +58 -0
- package/export/typechain/factories/ReimbursementPool__factory.js +350 -0
- package/export/typechain/factories/Rewards__factory.js +117 -0
- package/export/typechain/factories/SortitionPool__factory.js +610 -0
- package/export/typechain/factories/SortitionTree__factory.js +149 -0
- package/export/typechain/factories/TBTCVault__factory.js +480 -0
- package/export/typechain/factories/TBTC__factory.js +564 -0
- package/export/typechain/factories/TestERC20__factory.js +539 -0
- package/export/typechain/factories/TestERC721__factory.js +421 -0
- package/export/typechain/factories/TestEcdsaLib__factory.js +66 -0
- package/export/typechain/factories/TestRelay__factory.js +94 -0
- package/export/typechain/factories/TransparentUpgradeableProxy__factory.js +186 -0
- package/export/typechain/factories/VendingMachine__factory.js +549 -0
- package/export/typechain/factories/WalletRegistry__factory.js +1919 -0
- package/export/typechain/factories/Wallets__factory.js +143 -0
- package/export/typechain/index.js +132 -0
- package/export.json +15932 -503
- package/package.json +47 -26
- 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
|
+
});
|