Skip to content

Commit

Permalink
test: draft
Browse files Browse the repository at this point in the history
  • Loading branch information
PacificYield committed Dec 10, 2024
1 parent 6c15944 commit c593586
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 1 deletion.
2 changes: 1 addition & 1 deletion contracts/finance/ConfidentialVestingWalletCliff.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ConfidentialVestingWallet } from "./ConfidentialVestingWallet.sol";
* To use with the native asset, it is necessary to wrap the native asset to a ConfidentialERC20-like token.
*/

abstract contract VestingWalletCliff is ConfidentialVestingWallet {
abstract contract ConfidentialVestingWalletCliff is ConfidentialVestingWallet {
/// @notice Returned if the cliff duration is greater than the vesting duration.
error InvalidCliffDuration(uint64 cliffSeconds, uint64 durationSeconds);

Expand Down
16 changes: 16 additions & 0 deletions contracts/test/finance/TestConfidentialVestingWallet.sol
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 contracts/test/finance/TestConfidentialVestingWalletCliff.sol
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_) {
//
}
}
30 changes: 30 additions & 0 deletions test/finance/ConfidentialVestingWallet.fixture.ts
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;
}
114 changes: 114 additions & 0 deletions test/finance/ConfidentialVestingWallet.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { expect } from "chai";
import { parseUnits } from "ethers";
import { ethers } from "hardhat";

import { deployConfidentialERC20Fixture } 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.only("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.only("can release", async function () {
// 10M
const amount = parseUnits("10000000", 6);

let tx = await this.confidentialERC20.connect(this.signers.alice).mint(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));
});
});
20 changes: 20 additions & 0 deletions test/finance/ConfidentialVestingWalletCliff.fixture.ts
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 deployConfidentialVestingWalletFixture(
account: Signer,
beneficiaryAddress: string,
token: string,
startTimestamp: bigint,
duration: bigint,
cliff: bigint,
): Promise<TestConfidentialVestingWalletCliff> {
const contractFactory = await ethers.getContractFactory("TestConfidentialVestingWalletCliff");
const contract = await contractFactory
.connect(account)
.deploy(beneficiaryAddress, token, startTimestamp, duration, cliff);
await contract.waitForDeployment();
return contract;
}

0 comments on commit c593586

Please sign in to comment.