Skip to content

Commit

Permalink
Merge pull request #74 from zama-ai/test/events
Browse files Browse the repository at this point in the history
test: events for all contracts
  • Loading branch information
PacificYield authored Dec 2, 2024
2 parents 1ed27eb + 72d058f commit b46311c
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 80 deletions.
4 changes: 0 additions & 4 deletions contracts/governance/Comp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ abstract contract Comp is IComp, EncryptedERC20, EIP712, Ownable2Step {
/// @notice Emitted when an `account` (i.e. `delegator`) changes its delegate.
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

/// @notice Emitted when a `delegate` account's vote balance changes.
event DelegateVotesChanged(address indexed delegate);

/// @notice Emitted when the governor contract that can reencrypt votes changes.
/// @dev WARNING: it can be set to a malicious contract, which could reencrypt all user votes.
event NewGovernor(address indexed governor);
Expand Down Expand Up @@ -296,6 +293,5 @@ abstract contract Comp is IComp, EncryptedERC20, EIP712, Ownable2Step {

TFHE.allowThis(newVotes);
TFHE.allow(newVotes, delegatee);
emit DelegateVotesChanged(delegatee);
}
}
14 changes: 7 additions & 7 deletions contracts/governance/GovernorAlphaZama.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ abstract contract GovernorAlphaZama is Ownable2Step, GatewayCaller {
string description
);

/// @notice Emitted when a proposal is defeated either by lack of votes or by
/// more votes against.
/// @notice Emitted when a proposal is defeated either by (1) number of `for` votes inferior to the
/// quorum, (2) the number of `for` votes equal or inferior to `against` votes.
event ProposalDefeated(uint256 id);

/// @notice Emitted when a proposal has been executed in the Timelock.
Expand All @@ -79,12 +79,12 @@ abstract contract GovernorAlphaZama is Ownable2Step, GatewayCaller {
/// @notice Emitted when a proposal has been queued in the Timelock.
event ProposalQueued(uint256 id, uint256 eta);

/// @notice Emitted when a proposal has been rejected since the number of votes is lower
/// than the required threshold.
/// @notice Emitted when a proposal has been rejected since the number of votes of the proposer
/// is lower than the required threshold.
event ProposalRejected(uint256 id);

/// @notice Emitted when a proposal has been rejected since the number of votes is lower
/// than the required threshold.
/// @notice Emitted when a proposal has succeeded since the number of `for` votes is higher
/// than quorum and strictly higher than `against` votes.
event ProposalSucceeded(uint256 id);

/// @notice Emitted when a vote has been cast on a proposal.
Expand All @@ -99,7 +99,7 @@ abstract contract GovernorAlphaZama is Ownable2Step, GatewayCaller {
* @param PendingResults Proposal is not active and the result decryption is in progress.
* @param Canceled Proposal has been canceled by the proposer or by this contract's owner.
* @param Defeated Proposal has been defeated
* (either not reaching the quorum or `againstVotes` > `forVotes`).
* (either not reaching the quorum or `againstVotes` >= `forVotes`).
* @param Succeeded Proposal has succeeded (`forVotes` > `againstVotes`).
* @param Queued Proposal has been queued in the `Timelock`.
* @param Expired Proposal has expired (@dev This state exists only in read-only functions).
Expand Down
36 changes: 26 additions & 10 deletions test/encryptedERC20/EncryptedERC20.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { getSigners, initSigners } from "../signers";
import { deployEncryptedERC20Fixture, reencryptAllowance, reencryptBalance } from "./EncryptedERC20.fixture";

describe("EncryptedERC20", function () {
// @dev The placeholder is type(uint256).max --> 2**256 - 1.
const PLACEHOLDER = 2n ** 256n - 1n;

before(async function () {
await initSigners(2);
this.signers = await getSigners();
Expand All @@ -27,7 +30,7 @@ describe("EncryptedERC20", function () {
it("should mint the contract", async function () {
const mintAmount = 1000;
const tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount);
await tx.wait();
await expect(tx).to.emit(this.encryptedERC20, "Mint").withArgs(this.signers.alice, mintAmount);

expect(
await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address),
Expand All @@ -47,13 +50,15 @@ describe("EncryptedERC20", function () {
input.add64(transferAmount);
const encryptedTransferAmount = await input.encrypt();

tx = await this.encryptedERC20["transfer(address,bytes32,bytes)"](
this.signers.bob.address,
encryptedTransferAmount.handles[0],
encryptedTransferAmount.inputProof,
);
tx = await this.encryptedERC20
.connect(this.signers.alice)
[
"transfer(address,bytes32,bytes)"
](this.signers.bob.address, encryptedTransferAmount.handles[0], encryptedTransferAmount.inputProof);

await tx.wait();
await expect(tx)
.to.emit(this.encryptedERC20, "Transfer")
.withArgs(this.signers.alice, this.signers.bob, PLACEHOLDER);

// Decrypt Alice's balance
expect(
Expand All @@ -78,12 +83,17 @@ describe("EncryptedERC20", function () {
const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address);
input.add64(transferAmount);
const encryptedTransferAmount = await input.encrypt();

tx = await this.encryptedERC20["transfer(address,bytes32,bytes)"](
this.signers.bob.address,
encryptedTransferAmount.handles[0],
encryptedTransferAmount.inputProof,
);
await tx.wait();

// @dev There is no error-handling in this version of EncryptedERC20.
await expect(tx)
.to.emit(this.encryptedERC20, "Transfer")
.withArgs(this.signers.alice, this.signers.bob, PLACEHOLDER);

// Decrypt Alice's balance
expect(
Expand Down Expand Up @@ -117,7 +127,10 @@ describe("EncryptedERC20", function () {
encryptedAllowanceAmount.handles[0],
encryptedAllowanceAmount.inputProof,
);
await tx.wait();

await expect(tx)
.to.emit(this.encryptedERC20, "Approval")
.withArgs(this.signers.alice, this.signers.bob, PLACEHOLDER);

// @dev The allowance amount is set to be equal to the transfer amount.
expect(
Expand All @@ -142,7 +155,10 @@ describe("EncryptedERC20", function () {
encryptedTransferAmount.handles[0],
encryptedTransferAmount.inputProof,
);
await tx2.wait();

await expect(tx2)
.to.emit(this.encryptedERC20, "Transfer")
.withArgs(this.signers.alice, this.signers.bob, PLACEHOLDER);

// Decrypt Alice's balance
expect(
Expand Down
6 changes: 3 additions & 3 deletions test/encryptedERC20/EncryptedERC20WithErrors.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ export async function checkErrorCode(
const errorCodeHandle = await token.getErrorCodeForTransferId(transferId);
const errorCode = await reencryptEuint8(signers, instances, account, errorCodeHandle, tokenAddress);
switch (errorCode) {
case BigInt(0): {
case 0n: {
return "NO_ERROR";
}
case BigInt(1): {
case 1n: {
return "UNSUFFICIENT_BALANCE";
}
case BigInt(2): {
case 2n: {
return "UNSUFFICIENT_APPROVAL";
}
default: {
Expand Down
78 changes: 51 additions & 27 deletions test/encryptedERC20/EncryptedERC20WithErrors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { reencryptAllowance, reencryptBalance } from "./EncryptedERC20.fixture";
import { checkErrorCode, deployEncryptedERC20WithErrorsFixture } from "./EncryptedERC20WithErrors.fixture";

describe("EncryptedERC20WithErrors", function () {
const DEFAULT_TRANSFER_ID = BigInt(0);
const DEFAULT_SECOND_TRANSFER_ID = BigInt(1);
// @dev The placeholder is type(uint256).max --> 2**256 - 1.
const PLACEHOLDER = 2n ** 256n - 1n;

before(async function () {
await initSigners(2);
Expand All @@ -31,7 +31,7 @@ describe("EncryptedERC20WithErrors", function () {
it("should mint the contract", async function () {
const mintAmount = 1000;
const tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount);
await tx.wait();
await expect(tx).to.emit(this.encryptedERC20, "Mint").withArgs(this.signers.alice, mintAmount);

expect(
await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address),
Expand All @@ -43,6 +43,7 @@ describe("EncryptedERC20WithErrors", function () {
it("should transfer tokens between two users", async function () {
const mintAmount = 10_000;
const transferAmount = 1337;
const expectedTransferId = 0n;

let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount);
await tx.wait();
Expand All @@ -57,7 +58,9 @@ describe("EncryptedERC20WithErrors", function () {
"transfer(address,bytes32,bytes)"
](this.signers.bob.address, encryptedTransferAmount.handles[0], encryptedTransferAmount.inputProof);

await tx.wait();
await expect(tx)
.to.emit(this.encryptedERC20, "Transfer")
.withArgs(this.signers.alice, this.signers.bob, expectedTransferId);

// Decrypt Alice's balance
expect(
Expand All @@ -75,7 +78,7 @@ describe("EncryptedERC20WithErrors", function () {
this.signers,
this.instances,
"alice",
DEFAULT_TRANSFER_ID,
expectedTransferId,
this.encryptedERC20,
this.encryptedERC20Address,
),
Expand All @@ -87,7 +90,7 @@ describe("EncryptedERC20WithErrors", function () {
this.signers,
this.instances,
"bob",
DEFAULT_TRANSFER_ID,
expectedTransferId,
this.encryptedERC20,
this.encryptedERC20Address,
),
Expand All @@ -99,19 +102,24 @@ describe("EncryptedERC20WithErrors", function () {
// amount.
const mintAmount = 1000;
const transferAmount = 1337;
const expectedTransferId = 0n;

let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount);
await tx.wait();

const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address);
input.add64(transferAmount);
const encryptedTransferAmount = await input.encrypt();

tx = await this.encryptedERC20["transfer(address,bytes32,bytes)"](
this.signers.bob.address,
encryptedTransferAmount.handles[0],
encryptedTransferAmount.inputProof,
);
await tx.wait();

await expect(tx)
.to.emit(this.encryptedERC20, "Transfer")
.withArgs(this.signers.alice, this.signers.bob, expectedTransferId);

// Decrypt Alice's balance
expect(
Expand All @@ -129,7 +137,7 @@ describe("EncryptedERC20WithErrors", function () {
this.signers,
this.instances,
"bob",
DEFAULT_TRANSFER_ID,
expectedTransferId,
this.encryptedERC20,
this.encryptedERC20Address,
),
Expand Down Expand Up @@ -157,7 +165,10 @@ describe("EncryptedERC20WithErrors", function () {
encryptedAllowanceAmount.handles[0],
encryptedAllowanceAmount.inputProof,
);
await tx.wait();

await expect(tx)
.to.emit(this.encryptedERC20, "Approval")
.withArgs(this.signers.alice, this.signers.bob, PLACEHOLDER);

// @dev The allowance amount is set to be equal to the transfer amount.
expect(
Expand All @@ -171,18 +182,21 @@ describe("EncryptedERC20WithErrors", function () {
),
).to.equal(transferAmount);

const bobErc20 = this.encryptedERC20.connect(this.signers.bob);
const expectedTransferId1 = 0n;

const inputBob1 = this.instances.bob.createEncryptedInput(this.encryptedERC20Address, this.signers.bob.address);
inputBob1.add64(transferAmount + 1); // above allowance so next tx should actually not send any token
const encryptedTransferAmount = await inputBob1.encrypt();

const tx2 = await bobErc20["transferFrom(address,address,bytes32,bytes)"](
this.signers.alice.address,
this.signers.bob.address,
encryptedTransferAmount.handles[0],
encryptedTransferAmount.inputProof,
);
await tx2.wait();
const tx2 = await this.encryptedERC20
.connect(this.signers.bob)
[
"transferFrom(address,address,bytes32,bytes)"
](this.signers.alice.address, this.signers.bob.address, encryptedTransferAmount.handles[0], encryptedTransferAmount.inputProof);

await expect(tx2)
.to.emit(this.encryptedERC20, "Transfer")
.withArgs(this.signers.alice, this.signers.bob, expectedTransferId1);

// Decrypt Alice's balance
expect(
Expand All @@ -200,23 +214,27 @@ describe("EncryptedERC20WithErrors", function () {
this.signers,
this.instances,
"bob",
DEFAULT_TRANSFER_ID,
expectedTransferId1,
this.encryptedERC20,
this.encryptedERC20Address,
),
).to.equal("UNSUFFICIENT_APPROVAL");

const expectedTransferId2 = 1n;

const inputBob2 = this.instances.bob.createEncryptedInput(this.encryptedERC20Address, this.signers.bob.address);
inputBob2.add64(transferAmount); // below allowance so next tx should send token
const encryptedTransferAmount2 = await inputBob2.encrypt();

const tx3 = await bobErc20["transferFrom(address,address,bytes32,bytes)"](
this.signers.alice.address,
this.signers.bob.address,
encryptedTransferAmount2.handles[0],
encryptedTransferAmount2.inputProof,
);
await tx3.wait();
const tx3 = await await this.encryptedERC20
.connect(this.signers.bob)
[
"transferFrom(address,address,bytes32,bytes)"
](this.signers.alice.address, this.signers.bob.address, encryptedTransferAmount2.handles[0], encryptedTransferAmount2.inputProof);

await expect(tx3)
.to.emit(this.encryptedERC20, "Transfer")
.withArgs(this.signers.alice, this.signers.bob, expectedTransferId2);

// Decrypt Alice's balance
expect(
Expand Down Expand Up @@ -246,7 +264,7 @@ describe("EncryptedERC20WithErrors", function () {
this.signers,
this.instances,
"bob",
DEFAULT_SECOND_TRANSFER_ID,
expectedTransferId2,
this.encryptedERC20,
this.encryptedERC20Address,
),
Expand Down Expand Up @@ -439,6 +457,8 @@ describe("EncryptedERC20WithErrors", function () {
it("cannot reencrypt errors if the account is not a participant of the transfer", async function () {
const mintAmount = 10_000;
const transferAmount = 1337;
const expectedTransferId = 0;

let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount);
await tx.wait();

Expand All @@ -452,7 +472,11 @@ describe("EncryptedERC20WithErrors", function () {
"transfer(address,bytes32,bytes)"
](this.signers.bob.address, encryptedTransferAmount.handles[0], encryptedTransferAmount.inputProof);

const errorCodeHandle = await this.encryptedERC20.getErrorCodeForTransferId(DEFAULT_TRANSFER_ID);
await expect(tx)
.to.emit(this.encryptedERC20, "Transfer")
.withArgs(this.signers.alice, this.signers.bob, expectedTransferId);

const errorCodeHandle = await this.encryptedERC20.getErrorCodeForTransferId(expectedTransferId);

const { publicKey: publicKeyCarol, privateKey: privateKeyCarol } = this.instances.carol.generateKeypair();
const eip712Carol = this.instances.carol.createEIP712(publicKeyCarol, this.encryptedERC20Address);
Expand Down
Loading

0 comments on commit b46311c

Please sign in to comment.