@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,1012 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const hardhat_1 = require("hardhat");
|
|
27
|
+
const chai_1 = __importStar(require("chai"));
|
|
28
|
+
const smock_1 = require("@defi-wonderland/smock");
|
|
29
|
+
chai_1.default.use(smock_1.smock.matchers);
|
|
30
|
+
const { to1e18 } = hardhat_1.helpers.number;
|
|
31
|
+
const { createSnapshot, restoreSnapshot } = hardhat_1.helpers.snapshot;
|
|
32
|
+
const ZERO_ADDRESS = hardhat_1.ethers.constants.AddressZero;
|
|
33
|
+
const MAX_UINT256 = hardhat_1.ethers.constants.MaxUint256;
|
|
34
|
+
const fixture = async () => {
|
|
35
|
+
const [deployer, governance, bridge, thirdParty] = await hardhat_1.ethers.getSigners();
|
|
36
|
+
const Bank = await hardhat_1.ethers.getContractFactory("Bank");
|
|
37
|
+
const bank = await Bank.deploy();
|
|
38
|
+
await bank.deployed();
|
|
39
|
+
await bank.connect(deployer).updateBridge(bridge.address);
|
|
40
|
+
await bank.connect(deployer).transferOwnership(governance.address);
|
|
41
|
+
return {
|
|
42
|
+
deployer,
|
|
43
|
+
governance,
|
|
44
|
+
bridge,
|
|
45
|
+
thirdParty,
|
|
46
|
+
bank,
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
describe("Bank", () => {
|
|
50
|
+
// default Hardhat's networks blockchain, see https://hardhat.org/config/
|
|
51
|
+
const hardhatNetworkId = 31337;
|
|
52
|
+
let deployer;
|
|
53
|
+
let governance;
|
|
54
|
+
let bridge;
|
|
55
|
+
let thirdParty;
|
|
56
|
+
let bank;
|
|
57
|
+
before(async () => {
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-extra-semi
|
|
59
|
+
;
|
|
60
|
+
({ deployer, governance, bridge, thirdParty, bank } =
|
|
61
|
+
await hardhat_1.waffle.loadFixture(fixture));
|
|
62
|
+
});
|
|
63
|
+
describe("PERMIT_TYPEHASH", () => {
|
|
64
|
+
it("should be keccak256 of EIP2612 Permit message", async () => {
|
|
65
|
+
const expected = hardhat_1.ethers.utils.keccak256(hardhat_1.ethers.utils.toUtf8Bytes("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"));
|
|
66
|
+
(0, chai_1.expect)(await bank.PERMIT_TYPEHASH()).to.equal(expected);
|
|
67
|
+
// double-checking...
|
|
68
|
+
(0, chai_1.expect)(await bank.PERMIT_TYPEHASH()).to.equal("0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9");
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe("updateBridge", () => {
|
|
72
|
+
before(async () => {
|
|
73
|
+
await createSnapshot();
|
|
74
|
+
});
|
|
75
|
+
after(async () => {
|
|
76
|
+
await restoreSnapshot();
|
|
77
|
+
});
|
|
78
|
+
context("when called by a third party", () => {
|
|
79
|
+
it("should revert", async () => {
|
|
80
|
+
await (0, chai_1.expect)(bank.connect(thirdParty).updateBridge(thirdParty.address)).to.be.revertedWith("Ownable: caller is not the owner");
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
context("when called with 0-address bridge", () => {
|
|
84
|
+
it("should revert", async () => {
|
|
85
|
+
await (0, chai_1.expect)(bank.connect(governance).updateBridge(ZERO_ADDRESS)).to.be.revertedWith("Bridge address must not be 0x0");
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
context("when called by the governance", () => {
|
|
89
|
+
let tx;
|
|
90
|
+
before(async () => {
|
|
91
|
+
await createSnapshot();
|
|
92
|
+
tx = await bank.connect(governance).updateBridge(thirdParty.address);
|
|
93
|
+
});
|
|
94
|
+
after(async () => {
|
|
95
|
+
await restoreSnapshot();
|
|
96
|
+
});
|
|
97
|
+
it("should update the bridge", async () => {
|
|
98
|
+
(0, chai_1.expect)(await bank.bridge()).to.equal(thirdParty.address);
|
|
99
|
+
});
|
|
100
|
+
it("should emit the BridgeUpdated event", async () => {
|
|
101
|
+
await (0, chai_1.expect)(tx)
|
|
102
|
+
.to.emit(bank, "BridgeUpdated")
|
|
103
|
+
.withArgs(thirdParty.address);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe("transferBalance", () => {
|
|
108
|
+
const initialBalance = to1e18(500);
|
|
109
|
+
let spender;
|
|
110
|
+
let recipient;
|
|
111
|
+
before(async () => {
|
|
112
|
+
await createSnapshot();
|
|
113
|
+
const accounts = await (0, hardhat_1.getUnnamedAccounts)();
|
|
114
|
+
spender = await hardhat_1.ethers.getSigner(accounts[0]);
|
|
115
|
+
// eslint-disable-next-line prefer-destructuring
|
|
116
|
+
recipient = accounts[1];
|
|
117
|
+
await bank
|
|
118
|
+
.connect(bridge)
|
|
119
|
+
.increaseBalance(spender.address, initialBalance);
|
|
120
|
+
});
|
|
121
|
+
after(async () => {
|
|
122
|
+
await restoreSnapshot();
|
|
123
|
+
});
|
|
124
|
+
context("when the recipient is the zero address", () => {
|
|
125
|
+
it("should revert", async () => {
|
|
126
|
+
await (0, chai_1.expect)(bank.connect(spender).transferBalance(ZERO_ADDRESS, initialBalance)).to.be.revertedWith("Can not transfer to the zero address");
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
context("when the recipient is the bank address", () => {
|
|
130
|
+
it("should revert", async () => {
|
|
131
|
+
await (0, chai_1.expect)(bank.connect(spender).transferBalance(bank.address, initialBalance)).to.be.revertedWith("Can not transfer to the Bank address");
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
context("when the spender has not enough balance", () => {
|
|
135
|
+
it("should revert", async () => {
|
|
136
|
+
await (0, chai_1.expect)(bank
|
|
137
|
+
.connect(spender)
|
|
138
|
+
.transferBalance(recipient, initialBalance.add(1))).to.be.revertedWith("Transfer amount exceeds balance");
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
context("when the spender transfers part of their balance", () => {
|
|
142
|
+
const amount = to1e18(21);
|
|
143
|
+
let tx;
|
|
144
|
+
before(async () => {
|
|
145
|
+
await createSnapshot();
|
|
146
|
+
tx = await bank.connect(spender).transferBalance(recipient, amount);
|
|
147
|
+
});
|
|
148
|
+
after(async () => {
|
|
149
|
+
await restoreSnapshot();
|
|
150
|
+
});
|
|
151
|
+
it("should transfer the requested amount", async () => {
|
|
152
|
+
(0, chai_1.expect)(await bank.balanceOf(spender.address)).to.equal(initialBalance.sub(amount));
|
|
153
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient)).to.equal(amount);
|
|
154
|
+
});
|
|
155
|
+
it("should emit the BalanceTransferred event", async () => {
|
|
156
|
+
await (0, chai_1.expect)(tx)
|
|
157
|
+
.to.emit(bank, "BalanceTransferred")
|
|
158
|
+
.withArgs(spender.address, recipient, amount);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
context("when the spender transfers part of their balance in two transactions", () => {
|
|
162
|
+
const amount1 = to1e18(21);
|
|
163
|
+
const amount2 = to1e18(12);
|
|
164
|
+
before(async () => {
|
|
165
|
+
await createSnapshot();
|
|
166
|
+
await bank.connect(spender).transferBalance(recipient, amount1);
|
|
167
|
+
await bank.connect(spender).transferBalance(recipient, amount2);
|
|
168
|
+
});
|
|
169
|
+
after(async () => {
|
|
170
|
+
await restoreSnapshot();
|
|
171
|
+
});
|
|
172
|
+
it("should transfer the requested amount", async () => {
|
|
173
|
+
(0, chai_1.expect)(await bank.balanceOf(spender.address)).to.equal(initialBalance.sub(amount1).sub(amount2));
|
|
174
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient)).to.equal(amount1.add(amount2));
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
context("when the spender transfers their entire balance", () => {
|
|
178
|
+
const amount = initialBalance;
|
|
179
|
+
let tx;
|
|
180
|
+
before(async () => {
|
|
181
|
+
await createSnapshot();
|
|
182
|
+
tx = await bank.connect(spender).transferBalance(recipient, amount);
|
|
183
|
+
});
|
|
184
|
+
after(async () => {
|
|
185
|
+
await restoreSnapshot();
|
|
186
|
+
});
|
|
187
|
+
it("should transfer the entire balance", async () => {
|
|
188
|
+
(0, chai_1.expect)(await bank.balanceOf(spender.address)).to.equal(0);
|
|
189
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient)).to.equal(amount);
|
|
190
|
+
});
|
|
191
|
+
it("should emit the BalanceTransferred event", async () => {
|
|
192
|
+
await (0, chai_1.expect)(tx)
|
|
193
|
+
.to.emit(bank, "BalanceTransferred")
|
|
194
|
+
.withArgs(spender.address, recipient, amount);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
context("when the spender transfers 0 balance", () => {
|
|
198
|
+
const amount = 0;
|
|
199
|
+
let tx;
|
|
200
|
+
before(async () => {
|
|
201
|
+
await createSnapshot();
|
|
202
|
+
tx = await bank.connect(spender).transferBalance(recipient, amount);
|
|
203
|
+
});
|
|
204
|
+
after(async () => {
|
|
205
|
+
await restoreSnapshot();
|
|
206
|
+
});
|
|
207
|
+
it("should transfer no balance", async () => {
|
|
208
|
+
(0, chai_1.expect)(await bank.balanceOf(spender.address)).to.equal(initialBalance);
|
|
209
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient)).to.equal(0);
|
|
210
|
+
});
|
|
211
|
+
it("should emit the BalanceTransferred event", async () => {
|
|
212
|
+
await (0, chai_1.expect)(tx)
|
|
213
|
+
.to.emit(bank, "BalanceTransferred")
|
|
214
|
+
.withArgs(spender.address, recipient, 0);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
describe("approveBalanceAndCall", () => {
|
|
219
|
+
const amount = to1e18(11);
|
|
220
|
+
let owner;
|
|
221
|
+
let mockVault;
|
|
222
|
+
before(async () => {
|
|
223
|
+
const accounts = await (0, hardhat_1.getUnnamedAccounts)();
|
|
224
|
+
owner = await hardhat_1.ethers.getSigner(accounts[0]);
|
|
225
|
+
mockVault = await smock_1.smock.fake("IVault");
|
|
226
|
+
});
|
|
227
|
+
context("when the spender is the zero address", () => {
|
|
228
|
+
it("should revert", async () => {
|
|
229
|
+
await (0, chai_1.expect)(bank.connect(owner).approveBalanceAndCall(ZERO_ADDRESS, amount, [])).to.be.revertedWith("Can not approve to the zero address");
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
context("when the spender callback reverted", () => {
|
|
233
|
+
before(async () => {
|
|
234
|
+
await mockVault.receiveBalanceApproval.reverts();
|
|
235
|
+
});
|
|
236
|
+
after(async () => {
|
|
237
|
+
mockVault.receiveBalanceApproval.reset();
|
|
238
|
+
});
|
|
239
|
+
it("should revert", async () => {
|
|
240
|
+
await (0, chai_1.expect)(bank
|
|
241
|
+
.connect(owner)
|
|
242
|
+
.approveBalanceAndCall(mockVault.address, amount, [])).to.be.reverted;
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
context("when the spender had no approved balance before", () => {
|
|
246
|
+
let tx;
|
|
247
|
+
before(async () => {
|
|
248
|
+
await createSnapshot();
|
|
249
|
+
tx = await bank
|
|
250
|
+
.connect(owner)
|
|
251
|
+
.approveBalanceAndCall(mockVault.address, amount, "0x11");
|
|
252
|
+
});
|
|
253
|
+
after(async () => {
|
|
254
|
+
await restoreSnapshot();
|
|
255
|
+
mockVault.receiveBalanceApproval.reset();
|
|
256
|
+
});
|
|
257
|
+
it("should approve the requested amount", async () => {
|
|
258
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, mockVault.address)).to.equal(amount);
|
|
259
|
+
});
|
|
260
|
+
it("should emit the BalanceApproved event", async () => {
|
|
261
|
+
await (0, chai_1.expect)(tx)
|
|
262
|
+
.to.emit(bank, "BalanceApproved")
|
|
263
|
+
.withArgs(owner.address, mockVault.address, amount);
|
|
264
|
+
});
|
|
265
|
+
it("should call receiveBalanceApproval", async () => {
|
|
266
|
+
(0, chai_1.expect)(mockVault.receiveBalanceApproval).to.have.been.calledOnceWith(owner.address, amount, "0x11");
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
context("when the spender had an approved balance before", () => {
|
|
270
|
+
before(async () => {
|
|
271
|
+
await createSnapshot();
|
|
272
|
+
await bank
|
|
273
|
+
.connect(owner)
|
|
274
|
+
.approveBalance(mockVault.address, to1e18(1337));
|
|
275
|
+
await bank
|
|
276
|
+
.connect(owner)
|
|
277
|
+
.approveBalanceAndCall(mockVault.address, amount, "0x02");
|
|
278
|
+
});
|
|
279
|
+
after(async () => {
|
|
280
|
+
await restoreSnapshot();
|
|
281
|
+
mockVault.receiveBalanceApproval.reset();
|
|
282
|
+
});
|
|
283
|
+
it("should replace the previous allowance", async () => {
|
|
284
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, mockVault.address)).to.equal(amount);
|
|
285
|
+
});
|
|
286
|
+
it("should call receiveBalanceApproval", async () => {
|
|
287
|
+
(0, chai_1.expect)(mockVault.receiveBalanceApproval).to.have.been.calledOnceWith(owner.address, amount, "0x02");
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
describe("approveBalance", () => {
|
|
292
|
+
const amount = to1e18(10);
|
|
293
|
+
let owner;
|
|
294
|
+
let spender;
|
|
295
|
+
before(async () => {
|
|
296
|
+
const accounts = await (0, hardhat_1.getUnnamedAccounts)();
|
|
297
|
+
owner = await hardhat_1.ethers.getSigner(accounts[0]);
|
|
298
|
+
// eslint-disable-next-line prefer-destructuring
|
|
299
|
+
spender = accounts[1];
|
|
300
|
+
});
|
|
301
|
+
context("when the spender is the zero address", () => {
|
|
302
|
+
it("should revert", async () => {
|
|
303
|
+
await (0, chai_1.expect)(bank.connect(owner).approveBalance(ZERO_ADDRESS, amount)).to.be.revertedWith("Can not approve to the zero address");
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
context("when the spender had no approved balance before", () => {
|
|
307
|
+
let tx;
|
|
308
|
+
before(async () => {
|
|
309
|
+
await createSnapshot();
|
|
310
|
+
tx = await bank.connect(owner).approveBalance(spender, amount);
|
|
311
|
+
});
|
|
312
|
+
after(async () => {
|
|
313
|
+
await restoreSnapshot();
|
|
314
|
+
});
|
|
315
|
+
it("should approve the requested amount", async () => {
|
|
316
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender)).to.equal(amount);
|
|
317
|
+
});
|
|
318
|
+
it("should emit the BalanceApproved event", async () => {
|
|
319
|
+
await (0, chai_1.expect)(tx)
|
|
320
|
+
.to.emit(bank, "BalanceApproved")
|
|
321
|
+
.withArgs(owner.address, spender, amount);
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
context("when the spender had an approved balance before", () => {
|
|
325
|
+
before(async () => {
|
|
326
|
+
await createSnapshot();
|
|
327
|
+
await bank.connect(owner).approveBalance(spender, to1e18(1337));
|
|
328
|
+
await bank.connect(owner).approveBalance(spender, amount);
|
|
329
|
+
});
|
|
330
|
+
after(async () => {
|
|
331
|
+
await restoreSnapshot();
|
|
332
|
+
});
|
|
333
|
+
it("should replace the previous allowance", async () => {
|
|
334
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender)).to.equal(amount);
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
describe("increaseBalanceAllowance", () => {
|
|
339
|
+
const amount = to1e18(12);
|
|
340
|
+
let owner;
|
|
341
|
+
let spender;
|
|
342
|
+
before(async () => {
|
|
343
|
+
await createSnapshot();
|
|
344
|
+
const accounts = await (0, hardhat_1.getUnnamedAccounts)();
|
|
345
|
+
owner = await hardhat_1.ethers.getSigner(accounts[0]);
|
|
346
|
+
// eslint-disable-next-line prefer-destructuring
|
|
347
|
+
spender = accounts[1];
|
|
348
|
+
});
|
|
349
|
+
after(async () => {
|
|
350
|
+
await restoreSnapshot();
|
|
351
|
+
});
|
|
352
|
+
context("when the spender is the zero address", () => {
|
|
353
|
+
it("should revert", async () => {
|
|
354
|
+
await (0, chai_1.expect)(bank.connect(owner).increaseBalanceAllowance(ZERO_ADDRESS, amount)).to.be.revertedWith("Can not approve");
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
context("when the spender had no approved balance before", () => {
|
|
358
|
+
let tx;
|
|
359
|
+
before(async () => {
|
|
360
|
+
await createSnapshot();
|
|
361
|
+
tx = await bank.connect(owner).increaseBalanceAllowance(spender, amount);
|
|
362
|
+
});
|
|
363
|
+
after(async () => {
|
|
364
|
+
await restoreSnapshot();
|
|
365
|
+
});
|
|
366
|
+
it("should approve the requested amount", async () => {
|
|
367
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender)).to.equal(amount);
|
|
368
|
+
});
|
|
369
|
+
it("should emit the BalanceApproved event", async () => {
|
|
370
|
+
await (0, chai_1.expect)(tx)
|
|
371
|
+
.to.emit(bank, "BalanceApproved")
|
|
372
|
+
.withArgs(owner.address, spender, amount);
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
context("when the spender had an approved balance before", () => {
|
|
376
|
+
before(async () => {
|
|
377
|
+
await createSnapshot();
|
|
378
|
+
await bank.connect(owner).approveBalance(spender, to1e18(1337));
|
|
379
|
+
await bank.connect(owner).increaseBalanceAllowance(spender, amount);
|
|
380
|
+
});
|
|
381
|
+
after(async () => {
|
|
382
|
+
await restoreSnapshot();
|
|
383
|
+
});
|
|
384
|
+
it("should increase the previous allowance", async () => {
|
|
385
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender)).to.equal(to1e18(1337).add(amount));
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
context("when the spender has a maximum allowance", () => {
|
|
389
|
+
before(async () => {
|
|
390
|
+
await createSnapshot();
|
|
391
|
+
await bank.connect(owner).approveBalance(spender, MAX_UINT256);
|
|
392
|
+
});
|
|
393
|
+
after(async () => {
|
|
394
|
+
await restoreSnapshot();
|
|
395
|
+
});
|
|
396
|
+
it("should revert", async () => {
|
|
397
|
+
await (0, chai_1.expect)(bank.connect(owner).increaseBalanceAllowance(spender, to1e18(1))).to.be.reverted;
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
describe("decreaseBalanceAllowance", () => {
|
|
402
|
+
const approvedAmount = to1e18(99);
|
|
403
|
+
let owner;
|
|
404
|
+
let spender;
|
|
405
|
+
before(async () => {
|
|
406
|
+
await createSnapshot();
|
|
407
|
+
const accounts = await (0, hardhat_1.getUnnamedAccounts)();
|
|
408
|
+
owner = await hardhat_1.ethers.getSigner(accounts[0]);
|
|
409
|
+
// eslint-disable-next-line prefer-destructuring
|
|
410
|
+
spender = accounts[1];
|
|
411
|
+
});
|
|
412
|
+
after(async () => {
|
|
413
|
+
await restoreSnapshot();
|
|
414
|
+
});
|
|
415
|
+
context("when the spender is the zero address", () => {
|
|
416
|
+
it("should revert", async () => {
|
|
417
|
+
await (0, chai_1.expect)(bank.connect(owner).decreaseBalanceAllowance(ZERO_ADDRESS, to1e18(1))).to.be.revertedWith("Can not decrease balance allowance below zero");
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
context("when the spender had no approved balance before", () => {
|
|
421
|
+
it("should revert", async () => {
|
|
422
|
+
await (0, chai_1.expect)(bank.connect(owner).decreaseBalanceAllowance(spender, to1e18(1))).to.be.revertedWith("Can not decrease balance allowance below zero");
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
context("when the spender had an approved balance before", () => {
|
|
426
|
+
const decreaseBy = to1e18(3);
|
|
427
|
+
before(async () => {
|
|
428
|
+
await createSnapshot();
|
|
429
|
+
await bank.connect(owner).approveBalance(spender, approvedAmount);
|
|
430
|
+
await bank.connect(owner).decreaseBalanceAllowance(spender, decreaseBy);
|
|
431
|
+
});
|
|
432
|
+
after(async () => {
|
|
433
|
+
await restoreSnapshot();
|
|
434
|
+
});
|
|
435
|
+
it("should decrease the previous allowance", async () => {
|
|
436
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender)).to.equal(approvedAmount.sub(decreaseBy));
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
describe("transferBalanceFrom", () => {
|
|
441
|
+
const initialBalance = to1e18(500);
|
|
442
|
+
const approvedBalance = to1e18(45);
|
|
443
|
+
let owner;
|
|
444
|
+
let spender;
|
|
445
|
+
let recipient;
|
|
446
|
+
before(async () => {
|
|
447
|
+
await createSnapshot();
|
|
448
|
+
const accounts = await (0, hardhat_1.getUnnamedAccounts)();
|
|
449
|
+
owner = await hardhat_1.ethers.getSigner(accounts[0]);
|
|
450
|
+
spender = await hardhat_1.ethers.getSigner(accounts[1]);
|
|
451
|
+
// eslint-disable-next-line prefer-destructuring
|
|
452
|
+
recipient = accounts[2];
|
|
453
|
+
await bank.connect(bridge).increaseBalance(owner.address, initialBalance);
|
|
454
|
+
await bank.connect(owner).approveBalance(spender.address, approvedBalance);
|
|
455
|
+
});
|
|
456
|
+
after(async () => {
|
|
457
|
+
await restoreSnapshot();
|
|
458
|
+
});
|
|
459
|
+
context("when the recipient is the zero address", () => {
|
|
460
|
+
it("should revert", async () => {
|
|
461
|
+
await (0, chai_1.expect)(bank
|
|
462
|
+
.connect(spender)
|
|
463
|
+
.transferBalanceFrom(owner.address, ZERO_ADDRESS, approvedBalance)).to.be.revertedWith("Can not transfer to the zero address");
|
|
464
|
+
});
|
|
465
|
+
});
|
|
466
|
+
context("when the recipient is the bank address", () => {
|
|
467
|
+
it("should revert", async () => {
|
|
468
|
+
await (0, chai_1.expect)(bank
|
|
469
|
+
.connect(spender)
|
|
470
|
+
.transferBalanceFrom(owner.address, bank.address, approvedBalance)).to.be.revertedWith("Can not transfer to the Bank address");
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
context("when the spender has not enough balance approved", () => {
|
|
474
|
+
it("should revert", async () => {
|
|
475
|
+
await (0, chai_1.expect)(bank
|
|
476
|
+
.connect(spender)
|
|
477
|
+
.transferBalanceFrom(owner.address, recipient, approvedBalance.add(1))).to.be.revertedWith("Transfer amount exceeds allowance");
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
context("when the owner has not enough balance", () => {
|
|
481
|
+
const amount = initialBalance.add(1);
|
|
482
|
+
before(async () => {
|
|
483
|
+
await createSnapshot();
|
|
484
|
+
await bank.connect(owner).approveBalance(spender.address, amount);
|
|
485
|
+
});
|
|
486
|
+
after(async () => {
|
|
487
|
+
await restoreSnapshot();
|
|
488
|
+
});
|
|
489
|
+
it("should revert", async () => {
|
|
490
|
+
await (0, chai_1.expect)(bank
|
|
491
|
+
.connect(spender)
|
|
492
|
+
.transferBalanceFrom(owner.address, recipient, amount)).to.be.revertedWith("Transfer amount exceeds balance");
|
|
493
|
+
});
|
|
494
|
+
});
|
|
495
|
+
context("when the spender transfers part of the approved balance", () => {
|
|
496
|
+
const amount = to1e18(2);
|
|
497
|
+
let tx;
|
|
498
|
+
before(async () => {
|
|
499
|
+
await createSnapshot();
|
|
500
|
+
tx = await bank
|
|
501
|
+
.connect(spender)
|
|
502
|
+
.transferBalanceFrom(owner.address, recipient, amount);
|
|
503
|
+
});
|
|
504
|
+
after(async () => {
|
|
505
|
+
await restoreSnapshot();
|
|
506
|
+
});
|
|
507
|
+
it("should transfer the requested amount", async () => {
|
|
508
|
+
(0, chai_1.expect)(await bank.balanceOf(owner.address)).to.equal(initialBalance.sub(amount));
|
|
509
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient)).to.equal(amount);
|
|
510
|
+
});
|
|
511
|
+
it("should emit the BalanceTransferred event", async () => {
|
|
512
|
+
await (0, chai_1.expect)(tx)
|
|
513
|
+
.to.emit(bank, "BalanceTransferred")
|
|
514
|
+
.withArgs(owner.address, recipient, amount);
|
|
515
|
+
});
|
|
516
|
+
it("should reduce the spender allowance", async () => {
|
|
517
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender.address)).to.equal(approvedBalance.sub(amount));
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
context("when the spender transfers part of the approved balance in two transactions", () => {
|
|
521
|
+
const amount1 = to1e18(1);
|
|
522
|
+
const amount2 = to1e18(3);
|
|
523
|
+
let tx1;
|
|
524
|
+
let tx2;
|
|
525
|
+
before(async () => {
|
|
526
|
+
await createSnapshot();
|
|
527
|
+
tx1 = await bank
|
|
528
|
+
.connect(spender)
|
|
529
|
+
.transferBalanceFrom(owner.address, recipient, amount1);
|
|
530
|
+
tx2 = await bank
|
|
531
|
+
.connect(spender)
|
|
532
|
+
.transferBalanceFrom(owner.address, recipient, amount2);
|
|
533
|
+
});
|
|
534
|
+
after(async () => {
|
|
535
|
+
await restoreSnapshot();
|
|
536
|
+
});
|
|
537
|
+
it("should transfer the requested amount", async () => {
|
|
538
|
+
(0, chai_1.expect)(await bank.balanceOf(owner.address)).to.equal(initialBalance.sub(amount1).sub(amount2));
|
|
539
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient)).to.equal(amount1.add(amount2));
|
|
540
|
+
});
|
|
541
|
+
it("should emit BalanceTransferred events", async () => {
|
|
542
|
+
await (0, chai_1.expect)(tx1)
|
|
543
|
+
.to.emit(bank, "BalanceTransferred")
|
|
544
|
+
.withArgs(owner.address, recipient, amount1);
|
|
545
|
+
await (0, chai_1.expect)(tx2)
|
|
546
|
+
.to.emit(bank, "BalanceTransferred")
|
|
547
|
+
.withArgs(owner.address, recipient, amount2);
|
|
548
|
+
});
|
|
549
|
+
it("should reduce the spender allowance", async () => {
|
|
550
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender.address)).to.equal(approvedBalance.sub(amount1).sub(amount2));
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
context("when the spender transfers the entire approved balance", async () => {
|
|
554
|
+
const amount = approvedBalance;
|
|
555
|
+
before(async () => {
|
|
556
|
+
await createSnapshot();
|
|
557
|
+
await bank
|
|
558
|
+
.connect(spender)
|
|
559
|
+
.transferBalanceFrom(owner.address, recipient, amount);
|
|
560
|
+
});
|
|
561
|
+
after(async () => {
|
|
562
|
+
await restoreSnapshot();
|
|
563
|
+
});
|
|
564
|
+
it("should transfer the requested amount", async () => {
|
|
565
|
+
(0, chai_1.expect)(await bank.balanceOf(owner.address)).to.equal(initialBalance.sub(amount));
|
|
566
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient)).to.equal(amount);
|
|
567
|
+
});
|
|
568
|
+
it("should reduce the spender allowance to zero", async () => {
|
|
569
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender.address)).to.equal(0);
|
|
570
|
+
});
|
|
571
|
+
});
|
|
572
|
+
context("when the spender transfers the entire balance", async () => {
|
|
573
|
+
const amount = initialBalance;
|
|
574
|
+
before(async () => {
|
|
575
|
+
await createSnapshot();
|
|
576
|
+
await bank.connect(owner).approveBalance(spender.address, amount);
|
|
577
|
+
await bank
|
|
578
|
+
.connect(spender)
|
|
579
|
+
.transferBalanceFrom(owner.address, recipient, amount);
|
|
580
|
+
});
|
|
581
|
+
after(async () => {
|
|
582
|
+
await restoreSnapshot();
|
|
583
|
+
});
|
|
584
|
+
it("should transfer the requested amount", async () => {
|
|
585
|
+
(0, chai_1.expect)(await bank.balanceOf(owner.address)).to.equal(0);
|
|
586
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient)).to.equal(amount);
|
|
587
|
+
});
|
|
588
|
+
it("should reduce the spender allowance to zero", async () => {
|
|
589
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender.address)).to.equal(0);
|
|
590
|
+
});
|
|
591
|
+
});
|
|
592
|
+
context("when given the maximum allowance", () => {
|
|
593
|
+
const allowance = MAX_UINT256;
|
|
594
|
+
const amount = to1e18(21);
|
|
595
|
+
before(async () => {
|
|
596
|
+
await createSnapshot();
|
|
597
|
+
await bank.connect(owner).approveBalance(spender.address, allowance);
|
|
598
|
+
await bank
|
|
599
|
+
.connect(spender)
|
|
600
|
+
.transferBalanceFrom(owner.address, recipient, amount);
|
|
601
|
+
});
|
|
602
|
+
after(async () => {
|
|
603
|
+
await restoreSnapshot();
|
|
604
|
+
});
|
|
605
|
+
it("should not reduce the spender allowance", async () => {
|
|
606
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender.address)).to.equal(allowance);
|
|
607
|
+
});
|
|
608
|
+
});
|
|
609
|
+
});
|
|
610
|
+
describe("permit", () => {
|
|
611
|
+
const initialBalance = to1e18(1231);
|
|
612
|
+
const permittedBalance = to1e18(45);
|
|
613
|
+
let owner;
|
|
614
|
+
let spender;
|
|
615
|
+
let yesterday;
|
|
616
|
+
let tomorrow;
|
|
617
|
+
before(async () => {
|
|
618
|
+
await createSnapshot();
|
|
619
|
+
owner = hardhat_1.ethers.Wallet.createRandom();
|
|
620
|
+
await bank.connect(bridge).increaseBalance(owner.address, initialBalance);
|
|
621
|
+
const accounts = await (0, hardhat_1.getUnnamedAccounts)();
|
|
622
|
+
// eslint-disable-next-line prefer-destructuring
|
|
623
|
+
spender = accounts[1];
|
|
624
|
+
const lastBlockTimestamp = await hardhat_1.helpers.time.lastBlockTime();
|
|
625
|
+
yesterday = lastBlockTimestamp - 86400; // -1 day
|
|
626
|
+
tomorrow = lastBlockTimestamp + 86400; // +1 day
|
|
627
|
+
});
|
|
628
|
+
after(async () => {
|
|
629
|
+
await restoreSnapshot();
|
|
630
|
+
});
|
|
631
|
+
const getApproval = async (amount, spenderAddress, deadline) => {
|
|
632
|
+
// We use ethers.utils.SigningKey for a Wallet instead of
|
|
633
|
+
// Signer.signMessage to do not add '\x19Ethereum Signed Message:\n'
|
|
634
|
+
// prefix to the signed message. The '\x19` protection (see EIP191 for
|
|
635
|
+
// more details on '\x19' rationale and format) is already included in
|
|
636
|
+
// EIP2612 permit signed message and '\x19Ethereum Signed Message:\n'
|
|
637
|
+
// should not be used there.
|
|
638
|
+
const signingKey = new hardhat_1.ethers.utils.SigningKey(owner.privateKey);
|
|
639
|
+
const domainSeparator = await bank.DOMAIN_SEPARATOR();
|
|
640
|
+
const permitTypehash = await bank.PERMIT_TYPEHASH();
|
|
641
|
+
const nonce = await bank.nonce(owner.address);
|
|
642
|
+
const approvalDigest = hardhat_1.ethers.utils.keccak256(hardhat_1.ethers.utils.solidityPack(["bytes1", "bytes1", "bytes32", "bytes32"], [
|
|
643
|
+
"0x19",
|
|
644
|
+
"0x01",
|
|
645
|
+
domainSeparator,
|
|
646
|
+
hardhat_1.ethers.utils.keccak256(hardhat_1.ethers.utils.defaultAbiCoder.encode([
|
|
647
|
+
"bytes32",
|
|
648
|
+
"address",
|
|
649
|
+
"address",
|
|
650
|
+
"uint256",
|
|
651
|
+
"uint256",
|
|
652
|
+
"uint256",
|
|
653
|
+
], [
|
|
654
|
+
permitTypehash,
|
|
655
|
+
owner.address,
|
|
656
|
+
spenderAddress,
|
|
657
|
+
amount,
|
|
658
|
+
nonce,
|
|
659
|
+
deadline,
|
|
660
|
+
])),
|
|
661
|
+
]));
|
|
662
|
+
return hardhat_1.ethers.utils.splitSignature(signingKey.signDigest(approvalDigest));
|
|
663
|
+
};
|
|
664
|
+
context("when permission expired", () => {
|
|
665
|
+
it("should revert", async () => {
|
|
666
|
+
const deadline = yesterday;
|
|
667
|
+
const signature = await getApproval(permittedBalance, spender, deadline);
|
|
668
|
+
await (0, chai_1.expect)(bank
|
|
669
|
+
.connect(thirdParty)
|
|
670
|
+
.permit(owner.address, spender, permittedBalance, deadline, signature.v, signature.r, signature.s)).to.be.revertedWith("Permission expired");
|
|
671
|
+
});
|
|
672
|
+
});
|
|
673
|
+
context("when permission has an invalid signature", () => {
|
|
674
|
+
context("when owner does not match the permitting one", () => {
|
|
675
|
+
it("should revert", async () => {
|
|
676
|
+
const deadline = tomorrow;
|
|
677
|
+
const signature = await getApproval(permittedBalance, spender, deadline);
|
|
678
|
+
await (0, chai_1.expect)(bank.connect(thirdParty).permit(thirdParty.address, // does not match the signature
|
|
679
|
+
spender, permittedBalance, deadline, signature.v, signature.r, signature.s)).to.be.revertedWith("Invalid signature");
|
|
680
|
+
});
|
|
681
|
+
});
|
|
682
|
+
context("when spender does not match the signature", () => {
|
|
683
|
+
it("should revert", async () => {
|
|
684
|
+
const deadline = tomorrow;
|
|
685
|
+
const signature = await getApproval(permittedBalance, spender, deadline);
|
|
686
|
+
await (0, chai_1.expect)(bank.connect(thirdParty).permit(owner.address, thirdParty.address, // does not match the signature
|
|
687
|
+
permittedBalance, deadline, signature.v, signature.r, signature.s)).to.be.revertedWith("Invalid signature");
|
|
688
|
+
});
|
|
689
|
+
});
|
|
690
|
+
context("when permitted balance does not match the signature", () => {
|
|
691
|
+
it("should revert", async () => {
|
|
692
|
+
const deadline = tomorrow;
|
|
693
|
+
const signature = await getApproval(permittedBalance, spender, deadline);
|
|
694
|
+
await (0, chai_1.expect)(bank.connect(thirdParty).permit(owner.address, spender, permittedBalance.add(1), // does not match the signature
|
|
695
|
+
deadline, signature.v, signature.r, signature.s)).to.be.revertedWith("Invalid signature");
|
|
696
|
+
});
|
|
697
|
+
});
|
|
698
|
+
context("when permitted deadline does not match the signature", () => {
|
|
699
|
+
it("should revert", async () => {
|
|
700
|
+
const deadline = tomorrow;
|
|
701
|
+
const signature = await getApproval(permittedBalance, spender, deadline);
|
|
702
|
+
await (0, chai_1.expect)(bank.connect(thirdParty).permit(owner.address, spender, permittedBalance, deadline + 1, // does not match the signature
|
|
703
|
+
signature.v, signature.r, signature.s)).to.be.revertedWith("Invalid signature");
|
|
704
|
+
});
|
|
705
|
+
});
|
|
706
|
+
});
|
|
707
|
+
context("when the spender is the zero address", () => {
|
|
708
|
+
it("should revert", async () => {
|
|
709
|
+
const deadline = tomorrow;
|
|
710
|
+
const signature = await getApproval(permittedBalance, ZERO_ADDRESS, deadline);
|
|
711
|
+
await (0, chai_1.expect)(bank
|
|
712
|
+
.connect(thirdParty)
|
|
713
|
+
.permit(owner.address, ZERO_ADDRESS, permittedBalance, deadline, signature.v, signature.r, signature.s)).to.be.revertedWith("Can not approve to the zero address");
|
|
714
|
+
});
|
|
715
|
+
});
|
|
716
|
+
context("when the spender had no permitted balance before", () => {
|
|
717
|
+
let tx;
|
|
718
|
+
before(async () => {
|
|
719
|
+
await createSnapshot();
|
|
720
|
+
const deadline = tomorrow;
|
|
721
|
+
const signature = await getApproval(permittedBalance, spender, deadline);
|
|
722
|
+
tx = await bank
|
|
723
|
+
.connect(thirdParty)
|
|
724
|
+
.permit(owner.address, spender, permittedBalance, deadline, signature.v, signature.r, signature.s);
|
|
725
|
+
});
|
|
726
|
+
after(async () => {
|
|
727
|
+
await restoreSnapshot();
|
|
728
|
+
});
|
|
729
|
+
it("should approve the requested amount", async () => {
|
|
730
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender)).to.equal(permittedBalance);
|
|
731
|
+
});
|
|
732
|
+
it("should emit the BalanceApproved event", async () => {
|
|
733
|
+
await (0, chai_1.expect)(tx)
|
|
734
|
+
.to.emit(bank, "BalanceApproved")
|
|
735
|
+
.withArgs(owner.address, spender, permittedBalance);
|
|
736
|
+
});
|
|
737
|
+
it("should increment the nonce for the permitting owner", async () => {
|
|
738
|
+
(0, chai_1.expect)(await bank.nonce(owner.address)).to.equal(1);
|
|
739
|
+
(0, chai_1.expect)(await bank.nonce(spender)).to.equal(0);
|
|
740
|
+
});
|
|
741
|
+
});
|
|
742
|
+
context("when the spender had a permitted balance before", () => {
|
|
743
|
+
let tx;
|
|
744
|
+
before(async () => {
|
|
745
|
+
await createSnapshot();
|
|
746
|
+
const deadline = tomorrow;
|
|
747
|
+
let signature = await getApproval(to1e18(1337), spender, deadline);
|
|
748
|
+
await bank
|
|
749
|
+
.connect(thirdParty)
|
|
750
|
+
.permit(owner.address, spender, to1e18(1337), deadline, signature.v, signature.r, signature.s);
|
|
751
|
+
signature = await getApproval(permittedBalance, spender, deadline);
|
|
752
|
+
tx = await bank
|
|
753
|
+
.connect(thirdParty)
|
|
754
|
+
.permit(owner.address, spender, permittedBalance, deadline, signature.v, signature.r, signature.s);
|
|
755
|
+
});
|
|
756
|
+
after(async () => {
|
|
757
|
+
await restoreSnapshot();
|
|
758
|
+
});
|
|
759
|
+
it("should replace the previous approval", async () => {
|
|
760
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender)).to.equal(permittedBalance);
|
|
761
|
+
});
|
|
762
|
+
it("should emit the BalanceApproved event", async () => {
|
|
763
|
+
await (0, chai_1.expect)(tx)
|
|
764
|
+
.to.emit(bank, "BalanceApproved")
|
|
765
|
+
.withArgs(owner.address, spender, permittedBalance);
|
|
766
|
+
});
|
|
767
|
+
it("should increment the nonce for the permitting owner", async () => {
|
|
768
|
+
(0, chai_1.expect)(await bank.nonce(owner.address)).to.equal(2);
|
|
769
|
+
(0, chai_1.expect)(await bank.nonce(spender)).to.equal(0);
|
|
770
|
+
});
|
|
771
|
+
});
|
|
772
|
+
context("when given never expiring permit", () => {
|
|
773
|
+
const deadline = MAX_UINT256;
|
|
774
|
+
let signature;
|
|
775
|
+
before(async () => {
|
|
776
|
+
await createSnapshot();
|
|
777
|
+
signature = await getApproval(permittedBalance, spender, deadline);
|
|
778
|
+
});
|
|
779
|
+
after(async () => {
|
|
780
|
+
await restoreSnapshot();
|
|
781
|
+
});
|
|
782
|
+
it("should be accepted at any moment", async () => {
|
|
783
|
+
await hardhat_1.helpers.time.increaseTime(63113904); // +2 years
|
|
784
|
+
await bank
|
|
785
|
+
.connect(thirdParty)
|
|
786
|
+
.permit(owner.address, spender, permittedBalance, deadline, signature.v, signature.r, signature.s);
|
|
787
|
+
(0, chai_1.expect)(await bank.allowance(owner.address, spender)).to.equal(permittedBalance);
|
|
788
|
+
});
|
|
789
|
+
});
|
|
790
|
+
});
|
|
791
|
+
describe("increaseBalance", () => {
|
|
792
|
+
const amount = to1e18(10);
|
|
793
|
+
let recipient;
|
|
794
|
+
before(async () => {
|
|
795
|
+
await createSnapshot();
|
|
796
|
+
recipient = thirdParty.address;
|
|
797
|
+
});
|
|
798
|
+
after(async () => {
|
|
799
|
+
await restoreSnapshot();
|
|
800
|
+
});
|
|
801
|
+
context("when called by a third party", () => {
|
|
802
|
+
it("should revert", async () => {
|
|
803
|
+
await (0, chai_1.expect)(bank.connect(thirdParty).increaseBalance(recipient, amount)).to.be.revertedWith("Caller is not the bridge");
|
|
804
|
+
});
|
|
805
|
+
});
|
|
806
|
+
context("when called by the bridge", () => {
|
|
807
|
+
context("when increasing balance for the Bank", () => {
|
|
808
|
+
it("should revert", async () => {
|
|
809
|
+
await (0, chai_1.expect)(bank.connect(bridge).increaseBalance(bank.address, amount)).to.be.revertedWith("Can not increase balance for Bank");
|
|
810
|
+
});
|
|
811
|
+
});
|
|
812
|
+
context("when called for a valid recipient", () => {
|
|
813
|
+
let tx;
|
|
814
|
+
before(async () => {
|
|
815
|
+
await createSnapshot();
|
|
816
|
+
tx = await bank.connect(bridge).increaseBalance(recipient, amount);
|
|
817
|
+
});
|
|
818
|
+
after(async () => {
|
|
819
|
+
await restoreSnapshot();
|
|
820
|
+
});
|
|
821
|
+
it("should increase recipient's balance", async () => {
|
|
822
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient)).to.equal(amount);
|
|
823
|
+
});
|
|
824
|
+
it("should emit the BalanceIncreased event", async () => {
|
|
825
|
+
await (0, chai_1.expect)(tx)
|
|
826
|
+
.to.emit(bank, "BalanceIncreased")
|
|
827
|
+
.withArgs(recipient, amount);
|
|
828
|
+
});
|
|
829
|
+
});
|
|
830
|
+
});
|
|
831
|
+
});
|
|
832
|
+
describe("increaseBalances", () => {
|
|
833
|
+
const amount1 = to1e18(12);
|
|
834
|
+
const amount2 = to1e18(15);
|
|
835
|
+
const amount3 = to1e18(17);
|
|
836
|
+
let recipient1;
|
|
837
|
+
let recipient2;
|
|
838
|
+
let recipient3;
|
|
839
|
+
before(async () => {
|
|
840
|
+
await createSnapshot();
|
|
841
|
+
[recipient1, recipient2, recipient3] = await (0, hardhat_1.getUnnamedAccounts)();
|
|
842
|
+
});
|
|
843
|
+
after(async () => {
|
|
844
|
+
await restoreSnapshot();
|
|
845
|
+
});
|
|
846
|
+
context("when called by a third party", () => {
|
|
847
|
+
it("should revert", async () => {
|
|
848
|
+
await (0, chai_1.expect)(bank
|
|
849
|
+
.connect(thirdParty)
|
|
850
|
+
.increaseBalances([recipient1, recipient2, recipient3], [amount1, amount2, amount3])).to.be.revertedWith("Caller is not the bridge");
|
|
851
|
+
});
|
|
852
|
+
});
|
|
853
|
+
context("when called by the bridge", () => {
|
|
854
|
+
context("when increasing balance for the bank", () => {
|
|
855
|
+
it("should revert", async () => {
|
|
856
|
+
await (0, chai_1.expect)(bank
|
|
857
|
+
.connect(bridge)
|
|
858
|
+
.increaseBalances([recipient1, bank.address, recipient3], [amount1, amount2, amount3])).to.be.revertedWith("Can not increase balance for Bank");
|
|
859
|
+
});
|
|
860
|
+
});
|
|
861
|
+
context("when there is more recipients than amounts", () => {
|
|
862
|
+
it("should revert", async () => {
|
|
863
|
+
await (0, chai_1.expect)(bank
|
|
864
|
+
.connect(bridge)
|
|
865
|
+
.increaseBalances([recipient1, recipient2], [amount1])).to.be.revertedWith("Arrays must have the same length");
|
|
866
|
+
});
|
|
867
|
+
});
|
|
868
|
+
context("when there is more amounts than recipients", () => {
|
|
869
|
+
it("should revert", async () => {
|
|
870
|
+
await (0, chai_1.expect)(bank
|
|
871
|
+
.connect(bridge)
|
|
872
|
+
.increaseBalances([recipient1, recipient2], [amount1, amount2, amount3])).to.be.revertedWith("Arrays must have the same length");
|
|
873
|
+
});
|
|
874
|
+
});
|
|
875
|
+
context("when called for a valid recipient", () => {
|
|
876
|
+
let tx;
|
|
877
|
+
before(async () => {
|
|
878
|
+
await createSnapshot();
|
|
879
|
+
tx = await bank
|
|
880
|
+
.connect(bridge)
|
|
881
|
+
.increaseBalances([recipient1, recipient2, recipient3], [amount1, amount2, amount3]);
|
|
882
|
+
});
|
|
883
|
+
after(async () => {
|
|
884
|
+
await restoreSnapshot();
|
|
885
|
+
});
|
|
886
|
+
it("should increase recipients' balances", async () => {
|
|
887
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient1)).to.equal(amount1);
|
|
888
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient2)).to.equal(amount2);
|
|
889
|
+
(0, chai_1.expect)(await bank.balanceOf(recipient3)).to.equal(amount3);
|
|
890
|
+
});
|
|
891
|
+
it("should emit BalanceIncreased events", async () => {
|
|
892
|
+
await (0, chai_1.expect)(tx)
|
|
893
|
+
.to.emit(bank, "BalanceIncreased")
|
|
894
|
+
.withArgs(recipient1, amount1);
|
|
895
|
+
await (0, chai_1.expect)(tx)
|
|
896
|
+
.to.emit(bank, "BalanceIncreased")
|
|
897
|
+
.withArgs(recipient2, amount2);
|
|
898
|
+
await (0, chai_1.expect)(tx)
|
|
899
|
+
.to.emit(bank, "BalanceIncreased")
|
|
900
|
+
.withArgs(recipient3, amount3);
|
|
901
|
+
});
|
|
902
|
+
});
|
|
903
|
+
});
|
|
904
|
+
});
|
|
905
|
+
describe("increaseBalanceAndCall", () => {
|
|
906
|
+
const depositor1 = "0x30c371E0651B2Ff6062158ca1D95b07C7531c719";
|
|
907
|
+
const depositor2 = "0xb3464806d680722dBc678996F1670D19A42eA3e9";
|
|
908
|
+
const depositedAmount1 = to1e18(19);
|
|
909
|
+
const depositedAmount2 = to1e18(11);
|
|
910
|
+
const totalDepositedAmount = to1e18(30); // 19 + 11
|
|
911
|
+
let vault;
|
|
912
|
+
let tbtc;
|
|
913
|
+
before(async () => {
|
|
914
|
+
await createSnapshot();
|
|
915
|
+
const TBTC = await hardhat_1.ethers.getContractFactory("TBTC");
|
|
916
|
+
tbtc = await TBTC.deploy();
|
|
917
|
+
await tbtc.deployed();
|
|
918
|
+
const Vault = await hardhat_1.ethers.getContractFactory("TBTCVault");
|
|
919
|
+
vault = await Vault.deploy(bank.address, tbtc.address);
|
|
920
|
+
await vault.deployed();
|
|
921
|
+
await tbtc.connect(deployer).transferOwnership(vault.address);
|
|
922
|
+
});
|
|
923
|
+
after(async () => {
|
|
924
|
+
await restoreSnapshot();
|
|
925
|
+
});
|
|
926
|
+
context("when called by a third party", () => {
|
|
927
|
+
it("should revert", async () => {
|
|
928
|
+
await (0, chai_1.expect)(bank
|
|
929
|
+
.connect(thirdParty)
|
|
930
|
+
.increaseBalanceAndCall(vault.address, [depositor1, depositor2], [depositedAmount1, depositedAmount2])).to.be.revertedWith("Caller is not the bridge");
|
|
931
|
+
});
|
|
932
|
+
});
|
|
933
|
+
context("when called by the bridge", () => {
|
|
934
|
+
let tx;
|
|
935
|
+
before(async () => {
|
|
936
|
+
await createSnapshot();
|
|
937
|
+
tx = await bank
|
|
938
|
+
.connect(bridge)
|
|
939
|
+
.increaseBalanceAndCall(vault.address, [depositor1, depositor2], [depositedAmount1, depositedAmount2]);
|
|
940
|
+
});
|
|
941
|
+
after(async () => {
|
|
942
|
+
await restoreSnapshot();
|
|
943
|
+
});
|
|
944
|
+
context("when depositors array has greater length than deposited amounts array", () => {
|
|
945
|
+
it("should revert", async () => {
|
|
946
|
+
await (0, chai_1.expect)(bank
|
|
947
|
+
.connect(bridge)
|
|
948
|
+
.increaseBalanceAndCall(vault.address, [depositor1, depositor2], [depositedAmount1])).to.be.revertedWith("Arrays must have the same length");
|
|
949
|
+
});
|
|
950
|
+
});
|
|
951
|
+
context("when deposited amounts array has greater length than depositors array", () => {
|
|
952
|
+
it("should revert", async () => {
|
|
953
|
+
await (0, chai_1.expect)(bank
|
|
954
|
+
.connect(bridge)
|
|
955
|
+
.increaseBalanceAndCall(vault.address, [depositor1], [depositedAmount1, depositedAmount2])).to.be.revertedWith("Arrays must have the same length");
|
|
956
|
+
});
|
|
957
|
+
});
|
|
958
|
+
it("should increase vault's balance", async () => {
|
|
959
|
+
(0, chai_1.expect)(await bank.balanceOf(vault.address)).to.equal(totalDepositedAmount);
|
|
960
|
+
});
|
|
961
|
+
it("should emit BalanceIncreased event", async () => {
|
|
962
|
+
await (0, chai_1.expect)(tx)
|
|
963
|
+
.to.emit(bank, "BalanceIncreased")
|
|
964
|
+
.withArgs(vault.address, totalDepositedAmount);
|
|
965
|
+
});
|
|
966
|
+
it("should call the vault", async () => {
|
|
967
|
+
(0, chai_1.expect)(await tbtc.balanceOf(depositor1)).to.equal(depositedAmount1);
|
|
968
|
+
(0, chai_1.expect)(await tbtc.balanceOf(depositor2)).to.equal(depositedAmount2);
|
|
969
|
+
(0, chai_1.expect)(await tbtc.totalSupply()).to.equal(totalDepositedAmount);
|
|
970
|
+
});
|
|
971
|
+
});
|
|
972
|
+
});
|
|
973
|
+
describe("decreaseBalance", () => {
|
|
974
|
+
const initialBalance = to1e18(21);
|
|
975
|
+
const amount = to1e18(10);
|
|
976
|
+
let tx;
|
|
977
|
+
before(async () => {
|
|
978
|
+
await createSnapshot();
|
|
979
|
+
// first increase so that there is something to decrease from
|
|
980
|
+
await bank
|
|
981
|
+
.connect(bridge)
|
|
982
|
+
.increaseBalance(thirdParty.address, initialBalance);
|
|
983
|
+
tx = await bank.connect(thirdParty).decreaseBalance(amount);
|
|
984
|
+
});
|
|
985
|
+
after(async () => {
|
|
986
|
+
await restoreSnapshot();
|
|
987
|
+
});
|
|
988
|
+
it("should decrease caller's balance", async () => {
|
|
989
|
+
(0, chai_1.expect)(await bank.balanceOf(thirdParty.address)).to.equal(initialBalance.sub(amount));
|
|
990
|
+
});
|
|
991
|
+
it("should emit the BalanceDecreased event", async () => {
|
|
992
|
+
await (0, chai_1.expect)(tx)
|
|
993
|
+
.to.emit(bank, "BalanceDecreased")
|
|
994
|
+
.withArgs(thirdParty.address, amount);
|
|
995
|
+
});
|
|
996
|
+
});
|
|
997
|
+
describe("DOMAIN_SEPARATOR", () => {
|
|
998
|
+
it("should be keccak256 of EIP712 domain struct", async () => {
|
|
999
|
+
const { keccak256 } = hardhat_1.ethers.utils;
|
|
1000
|
+
const { defaultAbiCoder } = hardhat_1.ethers.utils;
|
|
1001
|
+
const { toUtf8Bytes } = hardhat_1.ethers.utils;
|
|
1002
|
+
const expected = keccak256(defaultAbiCoder.encode(["bytes32", "bytes32", "bytes32", "uint256", "address"], [
|
|
1003
|
+
keccak256(toUtf8Bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")),
|
|
1004
|
+
keccak256(toUtf8Bytes("TBTC Bank")),
|
|
1005
|
+
keccak256(toUtf8Bytes("1")),
|
|
1006
|
+
hardhatNetworkId,
|
|
1007
|
+
bank.address,
|
|
1008
|
+
]));
|
|
1009
|
+
(0, chai_1.expect)(await bank.DOMAIN_SEPARATOR()).to.equal(expected);
|
|
1010
|
+
});
|
|
1011
|
+
});
|
|
1012
|
+
});
|