From 3a79badd8bde0797419338a9c7ed8260e614f805 Mon Sep 17 00:00:00 2001 From: Piotr Dyraga Date: Tue, 16 Nov 2021 19:14:36 +0100 Subject: [PATCH 1/6] KEEP<>T delegate stake system tests The following scenarios are tested: 1. Given I am KEEP network managed grant staker and I have not undelegated my stake, when I authorize T staking contract, I can copy my delegation to T staking contract. 2. Given I am KEEP network managed grant staker and I have undelegated my stake, when I authorize T staking contract, I can not copy my delegation to T staking contract. 3. Given I am KEEP network non-managed grant staker and I have not undelegated my stake, when I authorize T staking contract, I can copy my delegation to T staking contract. 4. Given I am KEEP network non-managed grant staker and I have undelegated my stake, when I authorize T staking contract, I can not copy my delegation to T staking contract. 5. Given I am KEEP network liquid token staker and I have not undelegated my stake, when I authorize T staking contract, I can copy my delegation to T staking contract. 6. Given I am KEEP network liquid token staker and I have undelegated my stake, when I authorize T staking contract, I can not copy my delegation to T staking contract. --- contracts/test/IKeepRegistry.sol | 4 +- contracts/test/ITestKeepTokenStaking.sol | 2 + test/system/constants.js | 26 +++- test/system/staking.test.js | 151 ++++++++++++----------- 4 files changed, 103 insertions(+), 80 deletions(-) diff --git a/contracts/test/IKeepRegistry.sol b/contracts/test/IKeepRegistry.sol index 0211a837..8dae13b4 100644 --- a/contracts/test/IKeepRegistry.sol +++ b/contracts/test/IKeepRegistry.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.9; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IKeepRegistry { - function registryKeeper() external view returns (address); - function approveOperatorContract(address operatorContract) external; + + function registryKeeper() external view returns (address); } diff --git a/contracts/test/ITestKeepTokenStaking.sol b/contracts/test/ITestKeepTokenStaking.sol index 3287ca1e..0479d12a 100644 --- a/contracts/test/ITestKeepTokenStaking.sol +++ b/contracts/test/ITestKeepTokenStaking.sol @@ -9,4 +9,6 @@ interface ITestKeepTokenStaking is IKeepTokenStaking { address operator, address operatorContract ) external; + + function undelegate(address _operator) external; } diff --git a/test/system/constants.js b/test/system/constants.js index 911f7f85..11c10f1a 100644 --- a/test/system/constants.js +++ b/test/system/constants.js @@ -8,6 +8,26 @@ module.exports.nuCypherStakingEscrowAddress = module.exports.keepRegistryAddress = "0x1a9589F56c969d6b0D3787ea02322476eAd3fB05" -// A grant has been chosen arbitrarily to get a state allowing to perform test scenarios. -module.exports.keepManagedGrantAddress = - "0x6123fC47Fab68fB7905aDD5dcd3Bd1eb131556Dc" +// liquid token owner with 3,000,000 staked +module.exports.keepLiquidTokenStake = { + owner: "0x4A0A927043B01a7fB175BCa4F4837e3b817C5e6b", + operator: "0x64A8856cBD255765D16B901a0B899daefC78FB13", + authorizer: "0x5481188e698a5752c5cab6e2494fc2cfbb644f2d", + beneficiary: "0xa49f1b845a8086ac0b820ce6fa8ce92d223765d2", +} + +// standard grant delegation with 832,533 staked +module.exports.keepGrantStake = { + grantee: "0xf6f372DfAeCC1431186598c304e91B79Ce115766", + operator: "0x8Bd660A764Ca14155F3411a4526a028b6316CB3E", + authorizer: "0x826b18a8c61e976156a962613e2c189b3ee5f2cb", + beneficiary: "0xf6f372DfAeCC1431186598c304e91B79Ce115766", +} + +// managed grantee with 1,196,000 KEEP staked +module.exports.keepManagedGrantStake = { + grantee: "0x011074cA9EEff0836a68b170E46c4d20F8CAc727", + operator: "0xc6349eEC31048787676b6297ba71721376A8DdcF", + authorizer: "0x011074cA9EEff0836a68b170E46c4d20F8CAc727", + beneficiary: "0x011074cA9EEff0836a68b170E46c4d20F8CAc727", +} diff --git a/test/system/staking.test.js b/test/system/staking.test.js index 9b656b97..63a6869b 100644 --- a/test/system/staking.test.js +++ b/test/system/staking.test.js @@ -2,24 +2,20 @@ const { expect } = require("chai") const { resetFork, impersonateAccount, - to1e18, } = require("../helpers/contract-test-helpers") const { initContracts } = require("./init-contracts") -const { keepManagedGrantAddress } = require("./constants") -const { helpers } = require("hardhat") +const { + keepGrantStake, + keepLiquidTokenStake, + keepManagedGrantStake, +} = require("./constants") const describeFn = process.env.NODE_ENV === "system-test" ? describe : describe.skip -describeFn("System -- staking", () => { +describeFn("SystemTests: TokenStaking", () => { const startingBlock = 13619810 - // Roles. - // eslint-disable-next-line no-unused-vars - let governance - let beneficiary - let operator - let authorizer let purse // Contracts @@ -29,87 +25,92 @@ describeFn("System -- staking", () => { before(async () => { await resetFork(startingBlock) - governance = await ethers.getSigner(0) - beneficiary = await ethers.getSigner(1) - operator = await ethers.getSigner(2) - authorizer = await ethers.getSigner(3) - purse = await ethers.getSigner(4) + purse = await ethers.getSigner(0) const contracts = await initContracts() keepTokenStaking = contracts.keepTokenStaking tokenStaking = contracts.tokenStaking - - await delegateStake() - }) - - describe("test initial state", () => { - describe("legacy KEEP staking contract", () => { - it("should contain stake for operator", async () => { - expect( - await keepTokenStaking.eligibleStake( - operator.address, - tokenStaking.address - ) - ).to.be.equal(to1e18(100000)) - }) - }) - - describe("T staking contract", () => { - it("should not contain any stakes for operator", async () => { - const stakes = await tokenStaking.stakes(operator.address) - - expect(stakes[0]).to.be.equal(0) // tStake - expect(stakes[1]).to.be.equal(0) // keepInTStake - expect(stakes[2]).to.be.equal(0) // nuInTStake - }) - }) }) - describe("when operator stakes tokens from legacy KEEP staking contract", () => { - let tx + const describeStake = ( + ownerAddress, + operatorAddress, + authorizerAddress, + expectedStake + ) => { + let owner + let operator + let authorizer before(async () => { - tx = await tokenStaking.stakeKeep(operator.address) + // impersonate and drop 1 ETH for each account + owner = await impersonateAccount(ownerAddress, purse, "1") + operator = await impersonateAccount(operatorAddress, purse, "1") + authorizer = await impersonateAccount(authorizerAddress, purse, "1") }) - it("should copy delegation from the legacy KEEP staking contract to T staking contract", async () => { - const stakes = await tokenStaking.stakes(operator.address) + context("I have authorized T staking contract", () => { + before(async () => { + await keepTokenStaking + .connect(authorizer) + .authorizeOperatorContract(operatorAddress, tokenStaking.address) + }) - // KEEP -> T ratio is 0.5 (see init-contracts.js) and the operator has - // a stake equal to 100k KEEP. After `stakeKeep` it should have 50k of T. - expect(stakes[0]).to.be.equal(to1e18(0)) // tStake - expect(stakes[1]).to.be.equal(to1e18(50000)) // keepInTStake - expect(stakes[2]).to.be.equal(0) // nuInTStake - }) + context("I have not undelegated my legacy stake", () => { + describe("stakeKeep", () => { + before(async () => { + await tokenStaking.stakeKeep(operator.address) + }) + + it("should copy my stake to T staking contract", async () => { + const stakes = await tokenStaking.stakes(operatorAddress) + expect(stakes[0]).to.be.equal(0) // T + expect(stakes[1]).to.be.equal(expectedStake) // KEEP + expect(stakes[2]).to.be.equal(0) // NU + }) + }) + }) - it("should emit OperatorStaked event", async () => { - // TODO: Assert event params are correct. - await expect(tx).to.emit(tokenStaking, "OperatorStaked") + context("I have undelegated my legacy stake", () => { + before(async () => { + await keepTokenStaking.connect(owner).undelegate(operator.address) + }) + + describe("stakeKeep", () => { + it("should revert", async () => { + await expect( + tokenStaking.stakeKeep(operator.address) + ).to.be.revertedWith("Operator is already in use") + }) + }) + }) }) - }) + } - async function delegateStake() { - const managedGrant = await ethers.getContractAt( - "ITestManagedGrant", - keepManagedGrantAddress + context("Given I am KEEP network managed grant staker", () => { + describeStake( + keepManagedGrantStake.grantee, + keepManagedGrantStake.operator, + keepManagedGrantStake.authorizer, + "598000000000000000000000" ) - const granteeAddress = await managedGrant.grantee() - const grantee = await impersonateAccount(granteeAddress, purse, "5") + }) - const stakeDelegationData = ethers.utils.solidityPack( - ["address", "address", "address"], - [beneficiary.address, operator.address, authorizer.address] + context("Given I am KEEP network non-managed grant staker", () => { + describeStake( + keepGrantStake.grantee, + keepGrantStake.operator, + keepGrantStake.authorizer, + "416266500000000000000000" ) + }) - await managedGrant - .connect(grantee) - .stake(keepTokenStaking.address, to1e18(100000), stakeDelegationData) - - await keepTokenStaking - .connect(authorizer) - .authorizeOperatorContract(operator.address, tokenStaking.address) - - // Jump beyond the stake initialization period. - await helpers.time.increaseTime(43200) - } + context("Given I am KEEP network liquid token staker", () => { + describeStake( + keepLiquidTokenStake.owner, + keepLiquidTokenStake.operator, + keepLiquidTokenStake.authorizer, + "1500000000000000000000000" + ) + }) }) From 7e80a1b7b1faec74e78d252ca714c04de778b874 Mon Sep 17 00:00:00 2001 From: Piotr Dyraga Date: Tue, 16 Nov 2021 21:34:06 +0100 Subject: [PATCH 2/6] KEEP<>T top-up stake system tests The following scenarios are tested: 1. Given I am KEEP network liquid token staker and I copied my stake to T staking contract, when I executed top-up of my legacy stake, `topUpKeep` should top-up my stake in T staking contract. 2. Given I am KEEP network non-managed grant staker and I copied my stake to T staking contract, when I executed top-up of my legacy stake, `topUpKeep` should top-up my stake in T staking contract. 3. Given I am KEEP network managed grant staker and I copied my stake to T staking contract, when I executed top-up of my legacy stake, `topUpKeep` should top-up my stake in T staking contract. --- ...ManagedGrant.sol => IKeepManagedGrant.sol} | 2 +- contracts/test/IKeepToken.sol | 13 + contracts/test/IKeepTokenGrant.sol | 14 + contracts/test/ITestKeepTokenStaking.sol | 2 + test/system/constants.js | 20 +- test/system/init-contracts.js | 10 +- test/system/staking.test.js | 245 ++++++++++++++++-- 7 files changed, 269 insertions(+), 37 deletions(-) rename contracts/test/{ITestManagedGrant.sol => IKeepManagedGrant.sol} (83%) create mode 100644 contracts/test/IKeepToken.sol create mode 100644 contracts/test/IKeepTokenGrant.sol diff --git a/contracts/test/ITestManagedGrant.sol b/contracts/test/IKeepManagedGrant.sol similarity index 83% rename from contracts/test/ITestManagedGrant.sol rename to contracts/test/IKeepManagedGrant.sol index 65c71fa6..fac75ced 100644 --- a/contracts/test/ITestManagedGrant.sol +++ b/contracts/test/IKeepManagedGrant.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.9; import "../staking/KeepStake.sol"; -interface ITestManagedGrant is IManagedGrant { +interface IKeepManagedGrant is IManagedGrant { function stake( address stakingContract, uint256 amount, diff --git a/contracts/test/IKeepToken.sol b/contracts/test/IKeepToken.sol new file mode 100644 index 00000000..e054dc45 --- /dev/null +++ b/contracts/test/IKeepToken.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +pragma solidity 0.8.9; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IKeepToken is IERC20 { + function approveAndCall( + address spender, + uint256 value, + bytes memory extraData + ) external returns (bool success); +} diff --git a/contracts/test/IKeepTokenGrant.sol b/contracts/test/IKeepTokenGrant.sol new file mode 100644 index 00000000..4bdcf881 --- /dev/null +++ b/contracts/test/IKeepTokenGrant.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +pragma solidity 0.8.9; + +import "../staking/ILegacyTokenStaking.sol"; + +interface IKeepTokenGrant { + function stake( + uint256 id, + address stakingContract, + uint256 amount, + bytes memory extraData + ) external; +} diff --git a/contracts/test/ITestKeepTokenStaking.sol b/contracts/test/ITestKeepTokenStaking.sol index 0479d12a..26ef6b97 100644 --- a/contracts/test/ITestKeepTokenStaking.sol +++ b/contracts/test/ITestKeepTokenStaking.sol @@ -10,5 +10,7 @@ interface ITestKeepTokenStaking is IKeepTokenStaking { address operatorContract ) external; + function commitTopUp(address _operator) external; + function undelegate(address _operator) external; } diff --git a/test/system/constants.js b/test/system/constants.js index 11c10f1a..d823297c 100644 --- a/test/system/constants.js +++ b/test/system/constants.js @@ -1,4 +1,6 @@ module.exports.keepTokenAddress = "0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC" +module.exports.keepTokenGrantAddress = + "0x175989c71fd023d580c65f5dc214002687ff88b7" module.exports.nuCypherTokenAddress = "0x4fE83213D56308330EC302a8BD641f1d0113A4Cc" module.exports.keepTokenStakingAddress = @@ -16,18 +18,20 @@ module.exports.keepLiquidTokenStake = { beneficiary: "0xa49f1b845a8086ac0b820ce6fa8ce92d223765d2", } -// standard grant delegation with 832,533 staked -module.exports.keepGrantStake = { - grantee: "0xf6f372DfAeCC1431186598c304e91B79Ce115766", - operator: "0x8Bd660A764Ca14155F3411a4526a028b6316CB3E", - authorizer: "0x826b18a8c61e976156a962613e2c189b3ee5f2cb", - beneficiary: "0xf6f372DfAeCC1431186598c304e91B79Ce115766", -} - // managed grantee with 1,196,000 KEEP staked module.exports.keepManagedGrantStake = { grantee: "0x011074cA9EEff0836a68b170E46c4d20F8CAc727", operator: "0xc6349eEC31048787676b6297ba71721376A8DdcF", authorizer: "0x011074cA9EEff0836a68b170E46c4d20F8CAc727", beneficiary: "0x011074cA9EEff0836a68b170E46c4d20F8CAc727", + managedGrant: "0xac1a985E75C6a0b475b9c807Ad0705a988Be2D99", +} + +// standard grant delegation with 832,533 staked +module.exports.keepGrantStake = { + grantee: "0xf6f372DfAeCC1431186598c304e91B79Ce115766", + operator: "0x8Bd660A764Ca14155F3411a4526a028b6316CB3E", + authorizer: "0x826b18a8c61e976156a962613e2c189b3ee5f2cb", + beneficiary: "0xf6f372DfAeCC1431186598c304e91B79Ce115766", + grantID: 37, } diff --git a/test/system/init-contracts.js b/test/system/init-contracts.js index 838a6545..e72b0c71 100644 --- a/test/system/init-contracts.js +++ b/test/system/init-contracts.js @@ -4,6 +4,7 @@ const { keepTokenStakingAddress, nuCypherStakingEscrowAddress, keepRegistryAddress, + keepTokenGrantAddress, } = require("./constants.js") const { to1e18, @@ -18,6 +19,7 @@ async function initContracts() { const keepTokenStaking = await resolveKeepTokenStaking() const nuCypherStakingEscrow = await resolveNuCypherStakingEscrow() const keepRegistry = await resolveKeepRegistry() + const keepTokenGrant = await resolveKeepTokenGrant() const tToken = await deployTToken(to1e18(1000000)) @@ -59,13 +61,15 @@ async function initContracts() { .approveOperatorContract(tokenStaking.address) return { + keepToken: keepToken, + keepTokenGrant: keepTokenGrant, keepTokenStaking: keepTokenStaking, tokenStaking: tokenStaking, } } async function resolveKeepToken() { - return await ethers.getContractAt("IERC20", keepTokenAddress) + return await ethers.getContractAt("IKeepToken", keepTokenAddress) } async function resolveNuCypherToken() { @@ -90,6 +94,10 @@ async function resolveKeepRegistry() { return await ethers.getContractAt("IKeepRegistry", keepRegistryAddress) } +async function resolveKeepTokenGrant() { + return await ethers.getContractAt("IKeepTokenGrant", keepTokenGrantAddress) +} + async function deployTToken() { const TToken = await ethers.getContractFactory("T") const tToken = await TToken.deploy() diff --git a/test/system/staking.test.js b/test/system/staking.test.js index 63a6869b..e49404c8 100644 --- a/test/system/staking.test.js +++ b/test/system/staking.test.js @@ -2,12 +2,14 @@ const { expect } = require("chai") const { resetFork, impersonateAccount, + to1e18, } = require("../helpers/contract-test-helpers") const { initContracts } = require("./init-contracts") const { keepGrantStake, keepLiquidTokenStake, keepManagedGrantStake, + keepTokenGrantAddress, } = require("./constants") const describeFn = @@ -19,15 +21,17 @@ describeFn("SystemTests: TokenStaking", () => { let purse // Contracts + let keepToken let keepTokenStaking let tokenStaking - before(async () => { + beforeEach(async () => { await resetFork(startingBlock) purse = await ethers.getSigner(0) const contracts = await initContracts() + keepToken = contracts.keepToken keepTokenStaking = contracts.keepTokenStaking tokenStaking = contracts.tokenStaking }) @@ -42,37 +46,37 @@ describeFn("SystemTests: TokenStaking", () => { let operator let authorizer - before(async () => { + beforeEach(async () => { // impersonate and drop 1 ETH for each account owner = await impersonateAccount(ownerAddress, purse, "1") operator = await impersonateAccount(operatorAddress, purse, "1") authorizer = await impersonateAccount(authorizerAddress, purse, "1") }) - context("I have authorized T staking contract", () => { - before(async () => { + context("when I have authorized T staking contract", () => { + beforeEach(async () => { await keepTokenStaking .connect(authorizer) .authorizeOperatorContract(operatorAddress, tokenStaking.address) }) - context("I have not undelegated my legacy stake", () => { + context("when I have not undelegated my legacy stake", () => { describe("stakeKeep", () => { - before(async () => { + beforeEach(async () => { await tokenStaking.stakeKeep(operator.address) }) it("should copy my stake to T staking contract", async () => { const stakes = await tokenStaking.stakes(operatorAddress) - expect(stakes[0]).to.be.equal(0) // T - expect(stakes[1]).to.be.equal(expectedStake) // KEEP - expect(stakes[2]).to.be.equal(0) // NU + expect(stakes[0]).to.be.equal(0) // [T] + expect(stakes[1]).to.be.equal(expectedStake) // [KEEP] + expect(stakes[2]).to.be.equal(0) // [NU] }) }) }) - context("I have undelegated my legacy stake", () => { - before(async () => { + context("when I have undelegated my legacy stake", () => { + beforeEach(async () => { await keepTokenStaking.connect(owner).undelegate(operator.address) }) @@ -80,37 +84,224 @@ describeFn("SystemTests: TokenStaking", () => { it("should revert", async () => { await expect( tokenStaking.stakeKeep(operator.address) - ).to.be.revertedWith("Operator is already in use") + ).to.be.revertedWith("Nothing to sync") }) }) }) }) } - context("Given I am KEEP network managed grant staker", () => { + const describeTopUp = ( + ownerAddress, + operatorAddress, + authorizerAddress, + beneficiaryAddress, + topUpLegacyStakeFn, + expectedStake + ) => { + let owner + let operator + let authorizer + let beneficiary + + beforeEach(async () => { + // impersonate and drop 1 ETH for each account + owner = await impersonateAccount(ownerAddress, purse, "1") + operator = await impersonateAccount(operatorAddress, purse, "1") + authorizer = await impersonateAccount(authorizerAddress, purse, "1") + beneficiary = await impersonateAccount(beneficiaryAddress, purse, "1") + }) + + context("when I copied my stake to T staking contract", () => { + beforeEach(async () => { + await keepTokenStaking + .connect(authorizer) + .authorizeOperatorContract(operatorAddress, tokenStaking.address) + await tokenStaking.stakeKeep(operator.address) + }) + + context("when I executed top-up of my legacy stake", () => { + beforeEach(async () => { + await topUpLegacyStakeFn(owner, operator, authorizer, beneficiary) + }) + + describe("topUpKeep", () => { + beforeEach(async () => { + await tokenStaking.connect(owner).topUpKeep(operatorAddress) + }) + + it("should top-up my stake in T staking contract", async () => { + const stakes = await tokenStaking.stakes(operatorAddress) + expect(stakes[0]).to.be.equal(0) // [T] + expect(stakes[1]).to.be.equal(expectedStake) // [KEEP] + expect(stakes[2]).to.be.equal(0) // [NU] + }) + }) + }) + }) + } + + context("Given I am KEEP network liquid token staker", () => { + const ownerAddress = keepLiquidTokenStake.owner + const operatorAddress = keepLiquidTokenStake.operator + const authorizerAddress = keepLiquidTokenStake.authorizer + const beneficiaryAddress = keepLiquidTokenStake.beneficiary + + const expectedInitialStake = to1e18("1500000") // [T] + describeStake( - keepManagedGrantStake.grantee, - keepManagedGrantStake.operator, - keepManagedGrantStake.authorizer, - "598000000000000000000000" + ownerAddress, + operatorAddress, + authorizerAddress, + expectedInitialStake + ) + + const topUpAmountKeep = to1e18("1000") // [KEEP] + const expectedStakeAfterTopUp = to1e18("1500500") // [T] + + const topUpLegacyStakeFn = async ( + owner, + operator, + authorizer, + beneficiary + ) => { + // Send KEEP from the beneficiary account since the owner has 0 KEEP. + await keepToken + .connect(beneficiary) + .transfer(owner.address, topUpAmountKeep) + + const data = ethers.utils.solidityPack( + ["address", "address", "address"], + [beneficiary.address, operator.address, authorizer.address] + ) + await keepToken + .connect(owner) + .approveAndCall(keepTokenStaking.address, topUpAmountKeep, data) + + // Jump beyond the stake initialization period. + // Required to commit the top-up. + await helpers.time.increaseTime(43200) + + await keepTokenStaking.connect(owner).commitTopUp(operator.address) + } + + describeTopUp( + ownerAddress, + operatorAddress, + authorizerAddress, + beneficiaryAddress, + topUpLegacyStakeFn, + expectedStakeAfterTopUp ) }) - context("Given I am KEEP network non-managed grant staker", () => { + context("Given I am KEEP network managed grant staker", () => { + const ownerAddress = keepManagedGrantStake.grantee + const operatorAddress = keepManagedGrantStake.operator + const authorizerAddress = keepManagedGrantStake.authorizer + const beneficiaryAddress = keepManagedGrantStake.beneficiary + const managedGrantAddress = keepManagedGrantStake.managedGrant + + const expectedInitialStake = to1e18("598000") + describeStake( - keepGrantStake.grantee, - keepGrantStake.operator, - keepGrantStake.authorizer, - "416266500000000000000000" + ownerAddress, + operatorAddress, + authorizerAddress, + expectedInitialStake + ) + + const topUpAmountKeep = to1e18("100") // [KEEP] + const expectedStakeAfterTopUp = to1e18("598050") // [T] + + const topUpLegacyStakeFn = async ( + owner, + operator, + authorizer, + beneficiary + ) => { + const managedGrant = await ethers.getContractAt( + "IKeepManagedGrant", + managedGrantAddress + ) + + const data = ethers.utils.solidityPack( + ["address", "address", "address"], + [beneficiary.address, operator.address, authorizer.address] + ) + await managedGrant + .connect(owner) + .stake(keepTokenStaking.address, topUpAmountKeep, data) + + // Jump beyond the stake initialization period. + // Required to commit the top-up. + await helpers.time.increaseTime(43200) + + await keepTokenStaking.connect(owner).commitTopUp(operator.address) + } + + describeTopUp( + ownerAddress, + operatorAddress, + authorizerAddress, + beneficiaryAddress, + topUpLegacyStakeFn, + expectedStakeAfterTopUp ) }) - context("Given I am KEEP network liquid token staker", () => { + context("Given I am KEEP network non-managed grant staker", () => { + const ownerAddress = keepGrantStake.grantee + const operatorAddress = keepGrantStake.operator + const authorizerAddress = keepGrantStake.authorizer + const beneficiaryAddress = keepGrantStake.beneficiary + const grantID = keepGrantStake.grantID + + const expectedInitialStake = "416266500000000000000000" + describeStake( - keepLiquidTokenStake.owner, - keepLiquidTokenStake.operator, - keepLiquidTokenStake.authorizer, - "1500000000000000000000000" + ownerAddress, + operatorAddress, + authorizerAddress, + expectedInitialStake + ) + + const topUpAmountKeep = "100000000000000000" // [KEEP] + const expectedStakeAfterTopUp = "416266550000000000000000" // [T] + + const topUpLegacyStakeFn = async ( + owner, + operator, + authorizer, + beneficiary + ) => { + const tokenGrant = await ethers.getContractAt( + "IKeepTokenGrant", + keepTokenGrantAddress + ) + + const data = ethers.utils.solidityPack( + ["address", "address", "address"], + [beneficiary.address, operator.address, authorizer.address] + ) + await tokenGrant + .connect(owner) + .stake(grantID, keepTokenStaking.address, topUpAmountKeep, data) + + // Jump beyond the stake initialization period. + // Required to commit the top-up. + await helpers.time.increaseTime(43200) + + await keepTokenStaking.connect(owner).commitTopUp(operator.address) + } + + describeTopUp( + ownerAddress, + operatorAddress, + authorizerAddress, + beneficiaryAddress, + topUpLegacyStakeFn, + expectedStakeAfterTopUp ) }) }) From 8504713e9abaf0eb3c98cc66335d0ec9b07d77a0 Mon Sep 17 00:00:00 2001 From: Piotr Dyraga Date: Wed, 17 Nov 2021 10:45:07 +0100 Subject: [PATCH 3/6] Use real-world token amounts in system tests --- test/system/constants.js | 5 +++ test/system/init-contracts.js | 12 ++++--- test/system/staking.test.js | 66 ++++++++++++++--------------------- 3 files changed, 38 insertions(+), 45 deletions(-) diff --git a/test/system/constants.js b/test/system/constants.js index d823297c..e8c193df 100644 --- a/test/system/constants.js +++ b/test/system/constants.js @@ -1,3 +1,5 @@ +const { to1e18 } = require("../helpers/contract-test-helpers") + module.exports.keepTokenAddress = "0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC" module.exports.keepTokenGrantAddress = "0x175989c71fd023d580c65f5dc214002687ff88b7" @@ -16,6 +18,7 @@ module.exports.keepLiquidTokenStake = { operator: "0x64A8856cBD255765D16B901a0B899daefC78FB13", authorizer: "0x5481188e698a5752c5cab6e2494fc2cfbb644f2d", beneficiary: "0xa49f1b845a8086ac0b820ce6fa8ce92d223765d2", + keepStaked: to1e18("3000000"), } // managed grantee with 1,196,000 KEEP staked @@ -25,6 +28,7 @@ module.exports.keepManagedGrantStake = { authorizer: "0x011074cA9EEff0836a68b170E46c4d20F8CAc727", beneficiary: "0x011074cA9EEff0836a68b170E46c4d20F8CAc727", managedGrant: "0xac1a985E75C6a0b475b9c807Ad0705a988Be2D99", + keepStaked: to1e18("1196000"), } // standard grant delegation with 832,533 staked @@ -33,5 +37,6 @@ module.exports.keepGrantStake = { operator: "0x8Bd660A764Ca14155F3411a4526a028b6316CB3E", authorizer: "0x826b18a8c61e976156a962613e2c189b3ee5f2cb", beneficiary: "0xf6f372DfAeCC1431186598c304e91B79Ce115766", + keepStaked: to1e18("832533"), grantID: 37, } diff --git a/test/system/init-contracts.js b/test/system/init-contracts.js index e72b0c71..de5eaa1b 100644 --- a/test/system/init-contracts.js +++ b/test/system/init-contracts.js @@ -21,20 +21,20 @@ async function initContracts() { const keepRegistry = await resolveKeepRegistry() const keepTokenGrant = await resolveKeepTokenGrant() - const tToken = await deployTToken(to1e18(1000000)) + const tToken = await deployTToken(to1e18(10000000000)) const keepVendingMachine = await deployVendingMachine( keepToken, tToken, - to1e18(1000000), - to1e18(500000) + to1e18(999848780), + to1e18(4500000000) ) const nuCypherVendingMachine = await deployVendingMachine( nuCypherToken, tToken, - to1e18(1000000), - to1e18(500000) + to1e18(1350000000), + to1e18(4500000000) ) const keepStake = await deployKeepStake(keepTokenStaking) @@ -65,6 +65,8 @@ async function initContracts() { keepTokenGrant: keepTokenGrant, keepTokenStaking: keepTokenStaking, tokenStaking: tokenStaking, + keepVendingMachine: keepVendingMachine, + nuVendingMaching: nuCypherVendingMachine, } } diff --git a/test/system/staking.test.js b/test/system/staking.test.js index e49404c8..8fbfc1fa 100644 --- a/test/system/staking.test.js +++ b/test/system/staking.test.js @@ -23,6 +23,7 @@ describeFn("SystemTests: TokenStaking", () => { // Contracts let keepToken let keepTokenStaking + let keepVendingMachine let tokenStaking beforeEach(async () => { @@ -33,6 +34,7 @@ describeFn("SystemTests: TokenStaking", () => { const contracts = await initContracts() keepToken = contracts.keepToken keepTokenStaking = contracts.keepTokenStaking + keepVendingMachine = contracts.keepVendingMachine tokenStaking = contracts.tokenStaking }) @@ -40,7 +42,7 @@ describeFn("SystemTests: TokenStaking", () => { ownerAddress, operatorAddress, authorizerAddress, - expectedStake + keepStake ) => { let owner let operator @@ -67,10 +69,11 @@ describeFn("SystemTests: TokenStaking", () => { }) it("should copy my stake to T staking contract", async () => { + const stakeInT = await keepVendingMachine.conversionToT(keepStake) const stakes = await tokenStaking.stakes(operatorAddress) - expect(stakes[0]).to.be.equal(0) // [T] - expect(stakes[1]).to.be.equal(expectedStake) // [KEEP] - expect(stakes[2]).to.be.equal(0) // [NU] + expect(stakes[0]).to.be.equal(0) + expect(stakes[1]).to.be.equal(stakeInT.tAmount) + expect(stakes[2]).to.be.equal(0) }) }) }) @@ -97,7 +100,7 @@ describeFn("SystemTests: TokenStaking", () => { authorizerAddress, beneficiaryAddress, topUpLegacyStakeFn, - expectedStake + keepStake ) => { let owner let operator @@ -131,10 +134,11 @@ describeFn("SystemTests: TokenStaking", () => { }) it("should top-up my stake in T staking contract", async () => { + const stakeInT = await keepVendingMachine.conversionToT(keepStake) const stakes = await tokenStaking.stakes(operatorAddress) - expect(stakes[0]).to.be.equal(0) // [T] - expect(stakes[1]).to.be.equal(expectedStake) // [KEEP] - expect(stakes[2]).to.be.equal(0) // [NU] + expect(stakes[0]).to.be.equal(0) + expect(stakes[1]).to.be.equal(stakeInT.tAmount) + expect(stakes[2]).to.be.equal(0) }) }) }) @@ -146,18 +150,12 @@ describeFn("SystemTests: TokenStaking", () => { const operatorAddress = keepLiquidTokenStake.operator const authorizerAddress = keepLiquidTokenStake.authorizer const beneficiaryAddress = keepLiquidTokenStake.beneficiary + const keepStaked = keepLiquidTokenStake.keepStaked - const expectedInitialStake = to1e18("1500000") // [T] + describeStake(ownerAddress, operatorAddress, authorizerAddress, keepStaked) - describeStake( - ownerAddress, - operatorAddress, - authorizerAddress, - expectedInitialStake - ) - - const topUpAmountKeep = to1e18("1000") // [KEEP] - const expectedStakeAfterTopUp = to1e18("1500500") // [T] + const topUpAmountKeep = to1e18("1000") + const keepStakeAfterTopUp = keepStaked.add(topUpAmountKeep) const topUpLegacyStakeFn = async ( owner, @@ -191,7 +189,7 @@ describeFn("SystemTests: TokenStaking", () => { authorizerAddress, beneficiaryAddress, topUpLegacyStakeFn, - expectedStakeAfterTopUp + keepStakeAfterTopUp ) }) @@ -201,18 +199,12 @@ describeFn("SystemTests: TokenStaking", () => { const authorizerAddress = keepManagedGrantStake.authorizer const beneficiaryAddress = keepManagedGrantStake.beneficiary const managedGrantAddress = keepManagedGrantStake.managedGrant + const keepStaked = keepManagedGrantStake.keepStaked - const expectedInitialStake = to1e18("598000") + describeStake(ownerAddress, operatorAddress, authorizerAddress, keepStaked) - describeStake( - ownerAddress, - operatorAddress, - authorizerAddress, - expectedInitialStake - ) - - const topUpAmountKeep = to1e18("100") // [KEEP] - const expectedStakeAfterTopUp = to1e18("598050") // [T] + const topUpAmountKeep = to1e18("100") + const keepStakeAfterTopUp = keepStaked.add(topUpAmountKeep) const topUpLegacyStakeFn = async ( owner, @@ -246,7 +238,7 @@ describeFn("SystemTests: TokenStaking", () => { authorizerAddress, beneficiaryAddress, topUpLegacyStakeFn, - expectedStakeAfterTopUp + keepStakeAfterTopUp ) }) @@ -255,19 +247,13 @@ describeFn("SystemTests: TokenStaking", () => { const operatorAddress = keepGrantStake.operator const authorizerAddress = keepGrantStake.authorizer const beneficiaryAddress = keepGrantStake.beneficiary + const keepStaked = keepGrantStake.keepStaked const grantID = keepGrantStake.grantID - const expectedInitialStake = "416266500000000000000000" - - describeStake( - ownerAddress, - operatorAddress, - authorizerAddress, - expectedInitialStake - ) + describeStake(ownerAddress, operatorAddress, authorizerAddress, keepStaked) const topUpAmountKeep = "100000000000000000" // [KEEP] - const expectedStakeAfterTopUp = "416266550000000000000000" // [T] + const keepStakeAfterTopUp = keepStaked.add(topUpAmountKeep) const topUpLegacyStakeFn = async ( owner, @@ -301,7 +287,7 @@ describeFn("SystemTests: TokenStaking", () => { authorizerAddress, beneficiaryAddress, topUpLegacyStakeFn, - expectedStakeAfterTopUp + keepStakeAfterTopUp ) }) }) From 5bd37e652a5d23e9d1715ccae6e21af6280a1c23 Mon Sep 17 00:00:00 2001 From: Piotr Dyraga Date: Wed, 17 Nov 2021 11:57:49 +0100 Subject: [PATCH 4/6] KEEP<>T undelegate system tests The following scenarios are tested: 1. Given I am KEEP network liquid token staker, when I copied my stake to T staking contract, when I authorized and deauthorized application, `unstakeKeep` should release and let me undelegate my KEEP stake. 2. Given I am KEEP network managed grant staker, when I copied my stake to T staking contract, when I authorized and deauthorized application, `unstakeKeep` should release and let me undelegate my KEEP stake. 3. Given I am KEEP network non-managed grant staker, when I copied my stake to T staking contract, when I authorized and deauthorized application, `unstakeKeep` should release and let me undelegate my KEEP stake. --- contracts/test/ITestKeepTokenStaking.sol | 9 ++- test/system/staking.test.js | 98 +++++++++++++++++++++++- 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/contracts/test/ITestKeepTokenStaking.sol b/contracts/test/ITestKeepTokenStaking.sol index 26ef6b97..b2bb62a8 100644 --- a/contracts/test/ITestKeepTokenStaking.sol +++ b/contracts/test/ITestKeepTokenStaking.sol @@ -10,7 +10,12 @@ interface ITestKeepTokenStaking is IKeepTokenStaking { address operatorContract ) external; - function commitTopUp(address _operator) external; + function commitTopUp(address operator) external; - function undelegate(address _operator) external; + function undelegate(address operator) external; + + function getLocks(address operator) + external + view + returns (address[] memory creators, uint256[] memory expirations); } diff --git a/test/system/staking.test.js b/test/system/staking.test.js index 8fbfc1fa..0aa8f56e 100644 --- a/test/system/staking.test.js +++ b/test/system/staking.test.js @@ -18,6 +18,7 @@ const describeFn = describeFn("SystemTests: TokenStaking", () => { const startingBlock = 13619810 + let governance let purse // Contracts @@ -25,17 +26,23 @@ describeFn("SystemTests: TokenStaking", () => { let keepTokenStaking let keepVendingMachine let tokenStaking + let mockApplication beforeEach(async () => { await resetFork(startingBlock) - purse = await ethers.getSigner(0) + governance = await ethers.getSigner(0) + purse = await ethers.getSigner(1) const contracts = await initContracts() keepToken = contracts.keepToken keepTokenStaking = contracts.keepTokenStaking keepVendingMachine = contracts.keepVendingMachine tokenStaking = contracts.tokenStaking + + const ApplicationMock = await ethers.getContractFactory("ApplicationMock") + mockApplication = await ApplicationMock.deploy(tokenStaking.address) + await mockApplication.deployed() }) const describeStake = ( @@ -145,6 +152,74 @@ describeFn("SystemTests: TokenStaking", () => { }) } + const describeUndelegation = ( + ownerAddress, + operatorAddress, + authorizerAddress, + keepStake + ) => { + let owner + let operator + let authorizer + + beforeEach(async () => { + // impersonate and drop 1 ETH for each account + owner = await impersonateAccount(ownerAddress, purse, "1") + operator = await impersonateAccount(operatorAddress, purse, "1") + authorizer = await impersonateAccount(authorizerAddress, purse, "1") + }) + + context("when I copied my stake to T staking contract", () => { + beforeEach(async () => { + await keepTokenStaking + .connect(authorizer) + .authorizeOperatorContract(operatorAddress, tokenStaking.address) + await tokenStaking.stakeKeep(operator.address) + }) + + context("when I authorized and deauthorized application", () => { + beforeEach(async () => { + await tokenStaking + .connect(governance) + .approveApplication(mockApplication.address) + await tokenStaking + .connect(authorizer) + .increaseAuthorization( + operatorAddress, + mockApplication.address, + keepStake + ) + await tokenStaking + .connect(authorizer) + ["requestAuthorizationDecrease(address)"](operatorAddress) + await mockApplication.approveAuthorizationDecrease(operatorAddress) + }) + + describe("unstakeKeep", () => { + it("should release my KEEP stake", async () => { + await tokenStaking.connect(owner).unstakeKeep(operator.address) + const stakes = await tokenStaking.stakes(operatorAddress) + expect(stakes[0]).to.be.equal(0) + expect(stakes[1]).to.be.equal(0) + expect(stakes[2]).to.be.equal(0) + }) + + it("should let me undelegate my KEEP stake", async () => { + await keepTokenStaking.connect(owner).undelegate(operatorAddress) + // We can't test recover because KEEP stake is locked by tBTC + // deposits but we can ensure neither T staking contract nor the + // authorized application locked the stake. + const locks = await keepTokenStaking.getLocks(operatorAddress) + for (let i = 0; i < locks.creators.length; i++) { + expect(locks.creators[i]).not.to.be.equal(tokenStaking.address) + expect(locks.creators[i]).not.to.be.equal(mockApplication.address) + } + }) + }) + }) + }) + } + context("Given I am KEEP network liquid token staker", () => { const ownerAddress = keepLiquidTokenStake.owner const operatorAddress = keepLiquidTokenStake.operator @@ -191,6 +266,13 @@ describeFn("SystemTests: TokenStaking", () => { topUpLegacyStakeFn, keepStakeAfterTopUp ) + + describeUndelegation( + ownerAddress, + operatorAddress, + authorizerAddress, + keepStaked + ) }) context("Given I am KEEP network managed grant staker", () => { @@ -240,6 +322,13 @@ describeFn("SystemTests: TokenStaking", () => { topUpLegacyStakeFn, keepStakeAfterTopUp ) + + describeUndelegation( + ownerAddress, + operatorAddress, + authorizerAddress, + keepStaked + ) }) context("Given I am KEEP network non-managed grant staker", () => { @@ -289,5 +378,12 @@ describeFn("SystemTests: TokenStaking", () => { topUpLegacyStakeFn, keepStakeAfterTopUp ) + + describeUndelegation( + ownerAddress, + operatorAddress, + authorizerAddress, + keepStaked + ) }) }) From 965140e186e4412b44af30992c881c96ffc4ab0d Mon Sep 17 00:00:00 2001 From: Piotr Dyraga Date: Wed, 17 Nov 2021 18:04:05 +0100 Subject: [PATCH 5/6] KEEP<>T slashing/seizing system tests The following scenarios are tested: 1. Given I am KEEP network liquid token staker, when I copied my stake to T staking contract, when I authorized application, when I got slashed by the application, `processSlashing` should slash my KEEP stake. 2. Given I am KEEP network liquid token staker, when I copied my stake to T staking contract, when I authorized application, when I got slashed by the application, `notifyKeepStakeDiscrepancy` should revert. 3. Given I am KEEP network liquid token staker, when I copied my stake to T staking contract, when I authorized application, when the application seized my stake, `processSlashing` should seize my KEEP stake. 4. Given I am KEEP network liquid token staker, when I copied my stake to T staking contract, when I authorized application, when the application seized my stake, `notifyKeepStakeDiscrepancy` should revert. 5. Given I am KEEP network managed grant staker, when I copied my stake to T staking contract, when I authorized application, when I got slashed by the application, `processSlashing` should slash my KEEP stake. 6. Given I am KEEP network managed grant staker, when I copied my stake to T staking contract, when I authorized application, when I got slashed by the application, `notifyKeepStakeDiscrepancy` should revert. 7. Given I am KEEP network managed grant staker, when I copied my stake to T staking contract, when I authorized application, when the application seized my stake, `processSlashing` should seize my KEEP stake. 8. Given I am KEEP network managed grant staker, when I copied my stake to T staking contract, when I authorized application, when the application seized my stake, `notifyKeepStakeDiscrepancy` should revert. 9. Given I am KEEP network non-managed grant staker, when I copied my stake to T staking contract, when I authorized application, when I got slashed by the application, `processSlashing` should slash my KEEP stake. 10. Given I am KEEP network non-managed grant staker, when I copied my stake to T staking contract, when I authorized application, when I got slashed by the application, `notifyKeepStakeDiscrepancy` should revert. 11. Given I am KEEP network non-managed grant staker, when I copied my stake to T staking contract, when I authorized application, when the application seized my stake, `processSlashing` should seize my KEEP stake. 12. Given I am KEEP network non-managed grant staker, when I copied my stake to T staking contract, when I authorized application, when the application seized my stake, `notifyKeepStakeDiscrepancy` should revert. --- test/system/staking.test.js | 112 +++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 3 deletions(-) diff --git a/test/system/staking.test.js b/test/system/staking.test.js index 0aa8f56e..e67e8934 100644 --- a/test/system/staking.test.js +++ b/test/system/staking.test.js @@ -220,6 +220,109 @@ describeFn("SystemTests: TokenStaking", () => { }) } + const describeSlashing = (operatorAddress, authorizerAddress, keepStake) => { + let operator + let authorizer + + beforeEach(async () => { + // impersonate and drop 1 ETH for each account + operator = await impersonateAccount(operatorAddress, purse, "1") + authorizer = await impersonateAccount(authorizerAddress, purse, "1") + }) + + context("when I copied my stake to T staking contract", () => { + beforeEach(async () => { + await keepTokenStaking + .connect(authorizer) + .authorizeOperatorContract(operatorAddress, tokenStaking.address) + await tokenStaking.stakeKeep(operator.address) + }) + + context("when I authorized application", () => { + beforeEach(async () => { + await tokenStaking + .connect(governance) + .approveApplication(mockApplication.address) + await tokenStaking + .connect(authorizer) + .increaseAuthorization( + operatorAddress, + mockApplication.address, + keepStake + ) + }) + + context("when I got slashed by the application", () => { + const slashAmount = to1e18(9121) // amount in [T] + + beforeEach(async () => { + await mockApplication.slash(slashAmount, [operatorAddress]) + await tokenStaking.processSlashing(1) + }) + + describe("processSlashing", () => { + it("should slash my KEEP stake", async () => { + const slashAmountInKeep = + await keepVendingMachine.conversionFromT(slashAmount) + const expectedStakeInKeep = keepStake.sub( + slashAmountInKeep.wrappedAmount + ) + const actualStakeInKeep = await keepTokenStaking.eligibleStake( + operatorAddress, + tokenStaking.address + ) + + expect(actualStakeInKeep).to.equal(expectedStakeInKeep) + }) + }) + + describe("notifyKeepStakeDiscrepancy", () => { + it("should revert", async () => { + await expect( + tokenStaking.notifyKeepStakeDiscrepancy(operatorAddress) + ).to.be.revertedWith("There is no discrepancy") + }) + }) + }) + + context("when the application seized my stake", () => { + const seizeAmount = to1e18(4413) // amount in [T] + + beforeEach(async () => { + await mockApplication.seize(seizeAmount, 100, purse.address, [ + operatorAddress, + ]) + await tokenStaking.processSlashing(1) + }) + + describe("processSlashing", () => { + it("should seize my KEEP stake", async () => { + const seizeAmountInKeep = + await keepVendingMachine.conversionFromT(seizeAmount) + const expectedStakeInKeep = keepStake.sub( + seizeAmountInKeep.wrappedAmount + ) + const actualStakeInKeep = await keepTokenStaking.eligibleStake( + operatorAddress, + tokenStaking.address + ) + + expect(actualStakeInKeep).to.equal(expectedStakeInKeep) + }) + }) + + describe("notifyKeepStakeDiscrepancy", () => { + it("should revert", async () => { + await expect( + tokenStaking.notifyKeepStakeDiscrepancy(operatorAddress) + ).to.be.revertedWith("There is no discrepancy") + }) + }) + }) + }) + }) + } + context("Given I am KEEP network liquid token staker", () => { const ownerAddress = keepLiquidTokenStake.owner const operatorAddress = keepLiquidTokenStake.operator @@ -231,7 +334,6 @@ describeFn("SystemTests: TokenStaking", () => { const topUpAmountKeep = to1e18("1000") const keepStakeAfterTopUp = keepStaked.add(topUpAmountKeep) - const topUpLegacyStakeFn = async ( owner, operator, @@ -273,6 +375,8 @@ describeFn("SystemTests: TokenStaking", () => { authorizerAddress, keepStaked ) + + describeSlashing(operatorAddress, authorizerAddress, keepStaked) }) context("Given I am KEEP network managed grant staker", () => { @@ -287,7 +391,6 @@ describeFn("SystemTests: TokenStaking", () => { const topUpAmountKeep = to1e18("100") const keepStakeAfterTopUp = keepStaked.add(topUpAmountKeep) - const topUpLegacyStakeFn = async ( owner, operator, @@ -329,6 +432,8 @@ describeFn("SystemTests: TokenStaking", () => { authorizerAddress, keepStaked ) + + describeSlashing(operatorAddress, authorizerAddress, keepStaked) }) context("Given I am KEEP network non-managed grant staker", () => { @@ -343,7 +448,6 @@ describeFn("SystemTests: TokenStaking", () => { const topUpAmountKeep = "100000000000000000" // [KEEP] const keepStakeAfterTopUp = keepStaked.add(topUpAmountKeep) - const topUpLegacyStakeFn = async ( owner, operator, @@ -385,5 +489,7 @@ describeFn("SystemTests: TokenStaking", () => { authorizerAddress, keepStaked ) + + describeSlashing(operatorAddress, authorizerAddress, keepStaked) }) }) From bb5e4a38fa39c08aa91b018f23d689d9bc5cfc1c Mon Sep 17 00:00:00 2001 From: Piotr Dyraga Date: Mon, 20 Dec 2021 11:17:32 +0100 Subject: [PATCH 6/6] Explained token supplies in test init contracts script --- test/system/init-contracts.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/system/init-contracts.js b/test/system/init-contracts.js index de5eaa1b..5b3bf95f 100644 --- a/test/system/init-contracts.js +++ b/test/system/init-contracts.js @@ -21,19 +21,25 @@ async function initContracts() { const keepRegistry = await resolveKeepRegistry() const keepTokenGrant = await resolveKeepTokenGrant() + // 10 billion T minted const tToken = await deployTToken(to1e18(10000000000)) const keepVendingMachine = await deployVendingMachine( keepToken, tToken, + // 999,848,780 KEEP is the current KEEP total supply to1e18(999848780), + // 45% of T supply goes to KEEP vending machine to1e18(4500000000) ) const nuCypherVendingMachine = await deployVendingMachine( nuCypherToken, tToken, + // 1,350,000,000 is the NU total supply after pausing inflation + // (this number will be different for mainnet deployment but close to this one) to1e18(1350000000), + // 45% of T supply goes to KEEP vending machine to1e18(4500000000) )