-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: add unit tests and minor fixes
- Loading branch information
1 parent
481f54f
commit e536334
Showing
8 changed files
with
453 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// SPDX-License-Identifier: BSD-3-Clause-Clear | ||
pragma solidity ^0.8.24; | ||
|
||
import { ConfidentialVestingWallet } from "../../finance/ConfidentialVestingWallet.sol"; | ||
import { SepoliaZamaFHEVMConfig } from "fhevm/config/ZamaFHEVMConfig.sol"; | ||
|
||
contract TestConfidentialVestingWallet is SepoliaZamaFHEVMConfig, ConfidentialVestingWallet { | ||
constructor( | ||
address beneficiary_, | ||
address token_, | ||
uint64 startTimestamp_, | ||
uint64 duration_ | ||
) ConfidentialVestingWallet(beneficiary_, token_, startTimestamp_, duration_) { | ||
// | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
contracts/test/finance/TestConfidentialVestingWalletCliff.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// SPDX-License-Identifier: BSD-3-Clause-Clear | ||
pragma solidity ^0.8.24; | ||
|
||
import { ConfidentialVestingWalletCliff } from "../../finance/ConfidentialVestingWalletCliff.sol"; | ||
import { SepoliaZamaFHEVMConfig } from "fhevm/config/ZamaFHEVMConfig.sol"; | ||
|
||
contract TestConfidentialVestingWalletCliff is SepoliaZamaFHEVMConfig, ConfidentialVestingWalletCliff { | ||
constructor( | ||
address beneficiary_, | ||
address token_, | ||
uint64 startTimestamp_, | ||
uint64 duration_, | ||
uint64 cliff_ | ||
) ConfidentialVestingWalletCliff(beneficiary_, token_, startTimestamp_, duration_, cliff_) { | ||
// | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { Signer } from "ethers"; | ||
import { FhevmInstance } from "fhevmjs/node"; | ||
import { ethers } from "hardhat"; | ||
|
||
import type { ConfidentialVestingWallet, TestConfidentialVestingWallet } from "../../types"; | ||
import { reencryptEuint64 } from "../reencrypt"; | ||
|
||
export async function deployConfidentialVestingWalletFixture( | ||
account: Signer, | ||
beneficiaryAddress: string, | ||
token: string, | ||
startTimestamp: bigint, | ||
duration: bigint, | ||
): Promise<TestConfidentialVestingWallet> { | ||
const contractFactory = await ethers.getContractFactory("TestConfidentialVestingWallet"); | ||
const contract = await contractFactory.connect(account).deploy(beneficiaryAddress, token, startTimestamp, duration); | ||
await contract.waitForDeployment(); | ||
return contract; | ||
} | ||
|
||
export async function reencryptReleased( | ||
account: Signer, | ||
instance: FhevmInstance, | ||
vestingWallet: ConfidentialVestingWallet, | ||
vestingWalletAddress: string, | ||
): Promise<bigint> { | ||
const releasedHandled = await vestingWallet.released(); | ||
const releasedAmount = await reencryptEuint64(account, instance, releasedHandled, vestingWalletAddress); | ||
return releasedAmount; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import { expect } from "chai"; | ||
import { parseUnits } from "ethers"; | ||
import { ethers } from "hardhat"; | ||
|
||
import { deployConfidentialERC20Fixture, reencryptBalance } from "../confidentialERC20/ConfidentialERC20.fixture"; | ||
import { createInstance } from "../instance"; | ||
import { getSigners, initSigners } from "../signers"; | ||
import { deployConfidentialVestingWalletFixture, reencryptReleased } from "./ConfidentialVestingWallet.fixture"; | ||
|
||
describe("ConfidentialVestingWallet", function () { | ||
before(async function () { | ||
await initSigners(); | ||
this.signers = await getSigners(); | ||
this.instance = await createInstance(); | ||
}); | ||
|
||
beforeEach(async function () { | ||
const latestBlockNumber = await ethers.provider.getBlockNumber(); | ||
const block = await ethers.provider.getBlock(latestBlockNumber); | ||
|
||
this.beneficiary = this.signers.bob; | ||
this.beneficiaryAddress = this.signers.bob.address; | ||
|
||
const contractConfidentialERC20 = await deployConfidentialERC20Fixture( | ||
this.signers.alice, | ||
"Naraggara", | ||
"NARA", | ||
this.signers.alice.address, | ||
); | ||
this.confidentialERC20Address = await contractConfidentialERC20.getAddress(); | ||
this.confidentialERC20 = contractConfidentialERC20; | ||
this.startTimestamp = BigInt(block!.timestamp + 3600); | ||
this.duration = BigInt(36_000); // 36,000 seconds | ||
|
||
const contractConfidentialVestingWallet = await deployConfidentialVestingWalletFixture( | ||
this.signers.alice, | ||
this.beneficiaryAddress, | ||
this.confidentialERC20Address, | ||
this.startTimestamp, | ||
this.duration, | ||
); | ||
|
||
this.confidentialVestingWallet = contractConfidentialVestingWallet; | ||
this.confidentialVestingWalletAddress = await contractConfidentialVestingWallet.getAddress(); | ||
}); | ||
|
||
it("post-deployment state", async function () { | ||
expect(await this.confidentialVestingWallet.BENEFICIARY()).to.equal(this.beneficiaryAddress); | ||
expect(await this.confidentialVestingWallet.CONFIDENTIAL_ERC20()).to.equal(this.confidentialERC20); | ||
expect(await this.confidentialVestingWallet.DURATION()).to.equal(this.duration); | ||
expect(await this.confidentialVestingWallet.END_TIMESTAMP()).to.be.eq(this.startTimestamp + this.duration); | ||
expect(await this.confidentialVestingWallet.START_TIMESTAMP()).to.be.eq(this.startTimestamp); | ||
expect( | ||
await reencryptReleased( | ||
this.beneficiary, | ||
this.instance, | ||
this.confidentialVestingWallet, | ||
this.confidentialVestingWalletAddress, | ||
), | ||
).to.be.eq(0n); | ||
}); | ||
|
||
it("can release", async function () { | ||
// 10M | ||
const amount = parseUnits("10000000", 6); | ||
|
||
let tx = await this.confidentialERC20.connect(this.signers.alice).mint(this.signers.alice, amount); | ||
await tx.wait(); | ||
|
||
const input = this.instance.createEncryptedInput(this.confidentialERC20Address, this.signers.alice.address); | ||
input.add64(amount); | ||
const encryptedTransferAmount = await input.encrypt(); | ||
|
||
tx = await this.confidentialERC20 | ||
.connect(this.signers.alice) | ||
[ | ||
"transfer(address,bytes32,bytes)" | ||
](this.confidentialVestingWalletAddress, encryptedTransferAmount.handles[0], encryptedTransferAmount.inputProof); | ||
|
||
await tx.wait(); | ||
|
||
let nextTimestamp = this.startTimestamp; | ||
await ethers.provider.send("evm_setNextBlockTimestamp", [nextTimestamp.toString()]); | ||
|
||
tx = await this.confidentialVestingWallet.connect(this.beneficiary).release(); | ||
await expect(tx).to.emit(this.confidentialVestingWallet, "ConfidentialERC20Released"); | ||
|
||
// It should be equal to 0 because the vesting has not started. | ||
expect( | ||
await reencryptReleased( | ||
this.beneficiary, | ||
this.instance, | ||
this.confidentialVestingWallet, | ||
this.confidentialVestingWalletAddress, | ||
), | ||
).to.be.eq(0n); | ||
|
||
nextTimestamp = this.startTimestamp + this.duration / BigInt(4); | ||
await ethers.provider.send("evm_setNextBlockTimestamp", [nextTimestamp.toString()]); | ||
|
||
tx = await this.confidentialVestingWallet.connect(this.beneficiary).release(); | ||
await tx.wait(); | ||
|
||
// It should be equal to 1/4 of the amount vested. | ||
expect( | ||
await reencryptReleased( | ||
this.beneficiary, | ||
this.instance, | ||
this.confidentialVestingWallet, | ||
this.confidentialVestingWalletAddress, | ||
), | ||
).to.be.eq(BigInt(amount) / BigInt(4)); | ||
|
||
expect( | ||
await reencryptBalance(this.beneficiary, this.instance, this.confidentialERC20, this.confidentialERC20Address), | ||
).to.be.eq(BigInt(amount) / BigInt(4)); | ||
|
||
nextTimestamp = this.startTimestamp + this.duration / BigInt(2); | ||
await ethers.provider.send("evm_setNextBlockTimestamp", [nextTimestamp.toString()]); | ||
|
||
tx = await this.confidentialVestingWallet.connect(this.beneficiary).release(); | ||
await tx.wait(); | ||
|
||
// It should be equal to 1/4 of the amount vested since 1/4 was already collected. | ||
expect( | ||
await reencryptReleased( | ||
this.beneficiary, | ||
this.instance, | ||
this.confidentialVestingWallet, | ||
this.confidentialVestingWalletAddress, | ||
), | ||
).to.be.eq(BigInt(amount) / BigInt(2)); | ||
|
||
expect( | ||
await reencryptBalance(this.beneficiary, this.instance, this.confidentialERC20, this.confidentialERC20Address), | ||
).to.be.eq(BigInt(amount) / BigInt(2)); | ||
|
||
nextTimestamp = this.startTimestamp + this.duration; | ||
await ethers.provider.send("evm_setNextBlockTimestamp", [nextTimestamp.toString()]); | ||
|
||
tx = await this.confidentialVestingWallet.connect(this.beneficiary).release(); | ||
await tx.wait(); | ||
|
||
// It should be equal to 1/2 of the amount vested since 2/4 was already collected. | ||
expect( | ||
await reencryptReleased( | ||
this.beneficiary, | ||
this.instance, | ||
this.confidentialVestingWallet, | ||
this.confidentialVestingWalletAddress, | ||
), | ||
).to.be.eq(BigInt(amount)); | ||
|
||
expect( | ||
await reencryptBalance(this.beneficiary, this.instance, this.confidentialERC20, this.confidentialERC20Address), | ||
).to.be.eq(BigInt(amount)); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Signer } from "ethers"; | ||
import { ethers } from "hardhat"; | ||
|
||
import type { TestConfidentialVestingWalletCliff } from "../../types"; | ||
|
||
export async function deployConfidentialVestingWalletCliffFixture( | ||
account: Signer, | ||
beneficiaryAddress: string, | ||
token: string, | ||
startTimestamp: bigint, | ||
duration: bigint, | ||
cliffSeconds: bigint, | ||
): Promise<TestConfidentialVestingWalletCliff> { | ||
const contractFactory = await ethers.getContractFactory("TestConfidentialVestingWalletCliff"); | ||
const contract = await contractFactory | ||
.connect(account) | ||
.deploy(beneficiaryAddress, token, startTimestamp, duration, cliffSeconds); | ||
await contract.waitForDeployment(); | ||
return contract; | ||
} |
Oops, something went wrong.