'Vesting gradually in seconds in Hardhat (Solidity)
I have been studying vesting schedules in blockchain lately. I wanted to test if the implementation of vesting works correctly. First i made a test that has duration of 24 months and cliff duration of 6 months. After testing everything worked correctly, so I decided to create another test but in seconds. Here is the implementation:
it("Should be able to vest gradually (in seconds)", async () => {
// deploy vesting contract
let tokenVesting: TokenVesting = await new TokenVesting__factory(owner).deploy();
await tokenVesting.deployed();
await tokenVesting.initialize();
// send tokens to vesting contract
await expect(saleToken.transfer(tokenVesting.address, 1000))
.to.emit(saleToken, "Transfer")
.withArgs(owner.address, tokenVesting.address, 1000)
const currentBlock = await hh.ethers.provider.getBlock(await hh.ethers.provider.getBlockNumber());
let now: number = currentBlock.timestamp;
let vestingId = "vesting id";
let initiallyReleasablePercentage = 0;
let startTime: number = now + 1; // current time
let duration: number = 10; // 10 seconds
let cliffDuration: number = 4; // 4 seconds
let slicePeriodSeconds = 1; // 1 second
await tokenVesting.createVesting(
vestingId,
saleToken.address,
startTime,
duration,
cliffDuration,
initiallyReleasablePercentage,
slicePeriodSeconds
);
await saleToken.connect(owner).approve(tokenVesting.address, hh.ethers.utils.parseUnits("10", 18));
await tokenVesting.vest(vestingId, owner.address, hh.ethers.utils.parseUnits("10", 18));
/**
* vested amount should be 0 for the next 4 seconds, because cliff duration is 4 seconds
*/
expect(await tokenVesting.getReleasableAmount(tokenVesting.address, vestingId)).to.equal(0);
/**
* go ahead by 5 seconds -> current time is 5 seconds,
* should be able to vest 5 tokens because it reached cliff start time
*/
await hh.ethers.provider.send("evm_increaseTime", [5]);
await hh.ethers.provider.send("evm_mine", []);
expect(await tokenVesting.getReleasableAmount(owner.address, vestingId)).to.be.equal(5);
}
In this code first 10 lines are for deploying vesting contract and sending tokens to it. Then get current time using block.timestamp. Then I create fields that will be used to createVesting. duration is the total duration of a vesting, cliffDuration is cliff time, so time after which we can vest tokens and slicePeriodSeconds is the time that we have to wait after the previous release. Then under the tokenVesting.createVesting I send tokens to the user that will be tested and the amount is 10 and then testing starts.
Here is the problem
First test works fine because the releasable amount is 0. But then when I jump to the future by 5 seconds and test it, the test cracks. It shows that the releasable amount is 7 tokens but it should be 5 because we jumped to the middle of the token vesting period and total amount of tokens is 10.
My thoughts
It got me thinking that in these tests, time does not stop. It is going further. So when I jump by 5 second it logs time before and after creating vesting but when i m trying to getReleasableAmount the time passed and in this function gives me wrong amount of tokens. I don not really know if this is correct it is just my assumption.
Is it possible to somehow stop the time in hardhat testing after evm_increaseTime? When I tested the code but evm_increase_time was in months everything worked and releasable amount was as expected. But trying to test it in seconds when total vesting time is 10 seconds and cliff duration is 4 seconds it is not working as expected.
Has anybody had similar problem or know the solution to that (e.g. stopping the time in hardhat or something else)?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
