diff --git a/contracts/governance/Comp.sol b/contracts/governance/Comp.sol index 7e0a2a8..d0644df 100644 --- a/contracts/governance/Comp.sol +++ b/contracts/governance/Comp.sol @@ -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); @@ -296,6 +293,5 @@ abstract contract Comp is IComp, EncryptedERC20, EIP712, Ownable2Step { TFHE.allowThis(newVotes); TFHE.allow(newVotes, delegatee); - emit DelegateVotesChanged(delegatee); } } diff --git a/contracts/governance/GovernorAlphaZama.sol b/contracts/governance/GovernorAlphaZama.sol index 8adc1d1..d11df9e 100644 --- a/contracts/governance/GovernorAlphaZama.sol +++ b/contracts/governance/GovernorAlphaZama.sol @@ -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. @@ -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. @@ -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). diff --git a/test/encryptedERC20/EncryptedERC20.test.ts b/test/encryptedERC20/EncryptedERC20.test.ts index 608d0ef..b1e6710 100644 --- a/test/encryptedERC20/EncryptedERC20.test.ts +++ b/test/encryptedERC20/EncryptedERC20.test.ts @@ -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(); @@ -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), @@ -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( @@ -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( @@ -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( @@ -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( diff --git a/test/encryptedERC20/EncryptedERC20WithErrors.fixture.ts b/test/encryptedERC20/EncryptedERC20WithErrors.fixture.ts index d438d7e..031c141 100644 --- a/test/encryptedERC20/EncryptedERC20WithErrors.fixture.ts +++ b/test/encryptedERC20/EncryptedERC20WithErrors.fixture.ts @@ -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: { diff --git a/test/encryptedERC20/EncryptedERC20WithErrors.test.ts b/test/encryptedERC20/EncryptedERC20WithErrors.test.ts index 6ebb43c..3aa3a13 100644 --- a/test/encryptedERC20/EncryptedERC20WithErrors.test.ts +++ b/test/encryptedERC20/EncryptedERC20WithErrors.test.ts @@ -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); @@ -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), @@ -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(); @@ -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( @@ -75,7 +78,7 @@ describe("EncryptedERC20WithErrors", function () { this.signers, this.instances, "alice", - DEFAULT_TRANSFER_ID, + expectedTransferId, this.encryptedERC20, this.encryptedERC20Address, ), @@ -87,7 +90,7 @@ describe("EncryptedERC20WithErrors", function () { this.signers, this.instances, "bob", - DEFAULT_TRANSFER_ID, + expectedTransferId, this.encryptedERC20, this.encryptedERC20Address, ), @@ -99,6 +102,7 @@ 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(); @@ -106,12 +110,16 @@ describe("EncryptedERC20WithErrors", 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(); + + await expect(tx) + .to.emit(this.encryptedERC20, "Transfer") + .withArgs(this.signers.alice, this.signers.bob, expectedTransferId); // Decrypt Alice's balance expect( @@ -129,7 +137,7 @@ describe("EncryptedERC20WithErrors", function () { this.signers, this.instances, "bob", - DEFAULT_TRANSFER_ID, + expectedTransferId, this.encryptedERC20, this.encryptedERC20Address, ), @@ -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( @@ -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( @@ -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( @@ -246,7 +264,7 @@ describe("EncryptedERC20WithErrors", function () { this.signers, this.instances, "bob", - DEFAULT_SECOND_TRANSFER_ID, + expectedTransferId2, this.encryptedERC20, this.encryptedERC20Address, ), @@ -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(); @@ -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); diff --git a/test/governance/Comp.test.ts b/test/governance/Comp.test.ts index cc5def5..1e0ea18 100644 --- a/test/governance/Comp.test.ts +++ b/test/governance/Comp.test.ts @@ -11,6 +11,10 @@ import { deployCompFixture, reencryptCurrentVotes, reencryptPriorVotes } from ". import { delegateBySig } from "./DelegateBySig"; describe("Comp", function () { + // @dev The placeholder is type(uint256).max --> 2**256 - 1. + const PLACEHOLDER = 2n ** 256n - 1n; + const NULL_ADDRESS = "0x0000000000000000000000000000000000000000"; + before(async function () { await initSigners(3); this.signers = await getSigners(); @@ -36,7 +40,7 @@ describe("Comp", function () { encryptedTransferAmount.inputProof, ); - await tx.wait(); + await expect(tx).to.emit(this.comp, "Transfer").withArgs(this.signers.alice, this.signers.bob, PLACEHOLDER); // Decrypt Alice's balance expect(await reencryptBalance(this.signers, this.instances, "alice", this.comp, this.compAddress)).to.equal( @@ -51,7 +55,7 @@ describe("Comp", function () { it("can delegate tokens on-chain", async function () { const tx = await this.comp.connect(this.signers.alice).delegate(this.signers.bob.address); - await tx.wait(); + await expect(tx).to.emit(this.comp, "DelegateChanged").withArgs(this.signers.alice, NULL_ADDRESS, this.signers.bob); const latestBlockNumber = await ethers.provider.getBlockNumber(); await waitNBlocks(1); @@ -73,12 +77,13 @@ describe("Comp", function () { let latestBlockNumber = await ethers.provider.getBlockNumber(); const block = await ethers.provider.getBlock(latestBlockNumber); const expiry = block!.timestamp + 100; - const signature = await delegateBySig(delegator, delegatee.address, this.comp, nonce, expiry, false); + const signature = await delegateBySig(delegator, delegatee.address, this.comp, nonce, expiry); const tx = await this.comp .connect(this.signers.alice) .delegateBySig(delegator, delegatee, nonce, expiry, signature); - await tx.wait(); + + await expect(tx).to.emit(this.comp, "DelegateChanged").withArgs(this.signers.alice, NULL_ADDRESS, this.signers.bob); latestBlockNumber = await ethers.provider.getBlockNumber(); await waitNBlocks(1); @@ -154,7 +159,8 @@ describe("Comp", function () { const signature = await delegateBySig(delegator, delegatee.address, this.comp, nonce, expiry); const tx = await this.comp.connect(delegator).incrementNonce(); - await tx.wait(); + // @dev the newNonce is 1 + await expect(tx).to.emit(this.comp, "NonceIncremented").withArgs(delegator, BigInt("1")); // Cannot reuse same nonce when delegating by sig await expect(this.comp.delegateBySig(delegator, delegatee, nonce, expiry, signature)).to.be.revertedWithCustomError( @@ -202,7 +208,7 @@ describe("Comp", function () { ); const tx = await this.comp.connect(this.signers.alice).setGovernor(this.signers.bob); - await tx.wait(); + await expect(tx).to.emit(this.comp, "NewGovernor").withArgs(this.signers.bob); blockNumber = await ethers.provider.getBlockNumber(); @@ -294,7 +300,7 @@ describe("Comp", function () { it("getCurrentVote/getPriorVotes without any vote cannot be decrypted", async function () { // 1. If no checkpoint exists using getCurrentVotes let currentVoteHandle = await this.comp.connect(this.signers.bob).getCurrentVotes(this.signers.bob.address); - expect(currentVoteHandle).to.be.eq(BigInt(0)); + expect(currentVoteHandle).to.be.eq(0n); await expect( reencryptEuint64(this.signers, this.instances, "bob", currentVoteHandle, this.comp), @@ -309,7 +315,7 @@ describe("Comp", function () { .getPriorVotes(this.signers.bob.address, latestBlockNumber); // It is an encrypted constant that is not reencryptable by Bob. - expect(currentVoteHandle).not.to.be.eq(BigInt(0)); + expect(currentVoteHandle).not.to.be.eq(0n); await expect( reencryptEuint64(this.signers, this.instances, "bob", currentVoteHandle, this.comp), @@ -327,7 +333,7 @@ describe("Comp", function () { .getPriorVotes(this.signers.bob.address, latestBlockNumber); // It is an encrypted constant that is not reencryptable by Bob. - expect(currentVoteHandle).not.to.be.eq(BigInt(0)); + expect(currentVoteHandle).not.to.be.eq(0n); await expect( reencryptEuint64(this.signers, this.instances, "bob", currentVoteHandle, this.comp), @@ -393,7 +399,7 @@ describe("Comp", function () { it("governor address can access votes for any account", async function () { // Bob becomes the governor address. let tx = await this.comp.connect(this.signers.alice).setGovernor(this.signers.bob.address); - await tx.wait(); + await expect(tx).to.emit(this.comp, "NewGovernor").withArgs(this.signers.bob); // Alice delegates her votes to Carol. tx = await this.comp.connect(this.signers.alice).delegate(this.signers.carol.address); diff --git a/test/governance/GovernorAlphaZama.test.ts b/test/governance/GovernorAlphaZama.test.ts index 9435663..4a1bfd4 100644 --- a/test/governance/GovernorAlphaZama.test.ts +++ b/test/governance/GovernorAlphaZama.test.ts @@ -40,6 +40,10 @@ describe("GovernorAlphaZama", function () { const tx = await this.comp.setGovernor(this.governorAddress); await tx.wait(); + + this.VOTING_DELAY = await this.governor.VOTING_DELAY(); + this.VOTING_PERIOD = await this.governor.VOTING_PERIOD(); + this.TIMELOCK_DELAY = await this.timelock.delay(); }); it("can propose a vote that becomes active if votes match the token threshold", async function () { @@ -60,11 +64,25 @@ describe("GovernorAlphaZama", function () { this.compAddress, ); + const blockNumber = BigInt(await ethers.provider.getBlockNumber()); + const tx = await this.governor .connect(this.signers.bob) .propose(targets, values, signatures, calldatas, description); - await tx.wait(); + await expect(tx) + .to.emit(this.governor, "ProposalCreated") + .withArgs( + 1n, + this.signers.bob.address, + targets, + values, + signatures, + calldatas, + blockNumber + this.VOTING_DELAY + 1n, // @dev We add one since the transaction incremented the block number + blockNumber + this.VOTING_DELAY + this.VOTING_PERIOD + 1n, + description, + ); const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); let proposalInfo = await this.governor.getProposalInfo(proposalId); @@ -85,7 +103,7 @@ describe("GovernorAlphaZama", function () { }); it("anyone can propose a vote but it is rejected if votes are below the token threshold", async function () { - const transferAmount = (await this.governor.PROPOSAL_THRESHOLD()) - BigInt(1); + const transferAmount = (await this.governor.PROPOSAL_THRESHOLD()) - 1n; const targets = [this.signers.bob.address]; const values = ["0"]; const signatures = ["getBalanceOf(address)"]; @@ -168,7 +186,11 @@ describe("GovernorAlphaZama", function () { tx = await this.governor .connect(this.signers.bob) ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); - await tx.wait(); + + await expect(tx).to.emit(this.governor, "VoteCast").withArgs( + this.signers.bob, + 1n, // @dev proposalId + ); input = this.instances.carol.createEncryptedInput(this.governorAddress, this.signers.carol.address); input.addBool(true); @@ -176,7 +198,11 @@ describe("GovernorAlphaZama", function () { tx = await this.governor .connect(this.signers.carol) ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); - await tx.wait(); + + await expect(tx).to.emit(this.governor, "VoteCast").withArgs( + this.signers.carol, + 1n, // @dev proposalId + ); // Bob/Carol can reeencrypt his/her receipt let [hasVoted, support, votes] = await reencryptVoteReceipt( @@ -211,6 +237,7 @@ describe("GovernorAlphaZama", function () { // REQUEST DECRYPTION tx = await this.governor.requestVoteDecryption(proposalId); await tx.wait(); + let proposalInfo = await this.governor.getProposalInfo(proposalId); expect(proposalInfo.forVotes).to.be.eq(parseUnits(String(0), 6)); expect(proposalInfo.againstVotes).to.be.eq(parseUnits(String(0), 6)); @@ -220,24 +247,43 @@ describe("GovernorAlphaZama", function () { // POST-DECRYPTION RESULTS await awaitAllDecryptionResults(); proposalInfo = await this.governor.getProposalInfo(proposalId); - expect(proposalInfo.forVotes).to.be.eq(transferAmount * BigInt(2)); + expect(proposalInfo.forVotes).to.be.eq(transferAmount * 2n); expect(proposalInfo.againstVotes).to.be.eq(parseUnits(String(0), 6)); // 7 ==> Succeeded expect(proposalInfo.state).to.equal(7); + const block = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); + let nextBlockTimestamp: BigInt; + + if (block === null) { + throw "Block is null. Check RPC config."; + } else { + nextBlockTimestamp = BigInt(block.timestamp) + BigInt(30); + } + + await ethers.provider.send("evm_setNextBlockTimestamp", [nextBlockTimestamp.toString()]); + // QUEUING tx = await this.governor.queue(proposalId); - await tx.wait(); + await expect(tx) + .to.emit(this.governor, "ProposalQueued") + .withArgs( + 1n, // @dev proposalId, + nextBlockTimestamp + this.TIMELOCK_DELAY, + ); proposalInfo = await this.governor.getProposalInfo(proposalId); // 8 ==> Queued expect(proposalInfo.state).to.equal(8); const eta = proposalInfo.eta; + expect(eta).to.equal(nextBlockTimestamp + this.TIMELOCK_DELAY); // EXECUTE await ethers.provider.send("evm_setNextBlockTimestamp", [eta.toString()]); tx = await this.governor.execute(proposalId); - await tx.wait(); + await expect(tx).to.emit(this.governor, "ProposalExecuted").withArgs( + 1n, // @dev proposalId + ); proposalInfo = await this.governor.getProposalInfo(proposalId); // 10 ==> Executed @@ -250,7 +296,7 @@ describe("GovernorAlphaZama", function () { const signatures = ["getBalanceOf(address)"]; const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; const description = "description"; - const transferAmount = (await this.governor.QUORUM_VOTES()) - BigInt(1); + const transferAmount = (await this.governor.QUORUM_VOTES()) - 1n; // Bob receives enough to create a proposal but not enough to match the quorum. await transferTokensAndDelegate( @@ -299,6 +345,7 @@ describe("GovernorAlphaZama", function () { // REQUEST DECRYPTION tx = await this.governor.requestVoteDecryption(proposalId); + await tx.wait(); let proposalInfo = await this.governor.getProposalInfo(proposalId); expect(proposalInfo.forVotes).to.be.eq(parseUnits(String(0), 6)); @@ -316,14 +363,14 @@ describe("GovernorAlphaZama", function () { expect(proposalInfo.state).to.equal(6); }); - it("vote is rejected if forVotes < againstVotes", async function () { + it("vote is rejected if forVotes <= againstVotes", async function () { const targets = [this.signers.bob.address]; const values = ["0"]; const signatures = ["getBalanceOf(address)"]; const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; const description = "description"; const transferAmountFor = parseUnits(String(500_000), 6); - const transferAmountAgainst = parseUnits(String(500_000), 6) + BigInt(1); + const transferAmountAgainst = transferAmountFor; // Bob and Carol receive 200k tokens and delegate to themselves. await transferTokensAndDelegate( @@ -422,7 +469,13 @@ describe("GovernorAlphaZama", function () { it("only owner could queue setTimelockPendingAdmin then execute it, and then acceptTimelockAdmin", async function () { const block = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - const expiry = block!.timestamp + 60 * 60 * 24 * 2 + 60; + let expiry; + + if (block === null) { + throw "Block is null. Check RPC config."; + } else { + expiry = BigInt(block.timestamp) + this.TIMELOCK_DELAY + 1n; + } const tx = await this.governor.queueSetTimelockPendingAdmin(this.signers.bob, expiry); await tx.wait(); @@ -453,8 +506,15 @@ describe("GovernorAlphaZama", function () { const latestBlockNumber = await ethers.provider.getBlockNumber(); const block = await ethers.provider.getBlock(latestBlockNumber); - const expiry2 = block!.timestamp + 60 * 60 * 24 * 2 + 60; - const timeLockAdd = await this.timelock.getAddress(); + + let expiry2; + if (block === null) { + throw "Block is null. Check RPC config."; + } else { + expiry2 = BigInt(block.timestamp) + this.TIMELOCK_DELAY + 1n; + } + + const timeLockAdd = this.timelockAddress; const callData = ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.governorAddress]); const tx5 = await this.timelock .connect(this.signers.bob) @@ -667,7 +727,7 @@ describe("GovernorAlphaZama", function () { }); it("cannot cancel if state is Rejected/Defeated/Executed/Canceled", async function () { - let transferAmount = (await this.governor.PROPOSAL_THRESHOLD()) - BigInt(1); + let transferAmount = (await this.governor.PROPOSAL_THRESHOLD()) - 1n; const targets = [this.signers.bob.address]; const values = ["0"]; const signatures = ["getBalanceOf(address)"]; @@ -697,7 +757,7 @@ describe("GovernorAlphaZama", function () { ); // CANNOT CANCEL IF DEFEATED - transferAmount = (await this.governor.QUORUM_VOTES()) - BigInt(1); + transferAmount = (await this.governor.QUORUM_VOTES()) - 1n; await transferTokensAndDelegate( this.signers, @@ -851,7 +911,9 @@ describe("GovernorAlphaZama", function () { // @dev Alice is the governor's owner. tx = await this.governor.connect(this.signers.alice).cancel(proposalId); - await tx.wait(); + await expect(tx).to.emit(this.governor, "ProposalCanceled").withArgs( + 1n, // @dev proposalId + ); // 5 ==> Canceled expect((await this.governor.getProposalInfo(proposalId)).state).to.equal(5); diff --git a/test/utils/EncryptedErrors.test.ts b/test/utils/EncryptedErrors.test.ts index 4f327ef..4e277ad 100644 --- a/test/utils/EncryptedErrors.test.ts +++ b/test/utils/EncryptedErrors.test.ts @@ -7,7 +7,7 @@ import { getSigners, initSigners } from "../signers"; import { deployEncryptedErrors } from "./EncryptedErrors.fixture"; describe("EncryptedErrors", function () { - const NO_ERROR_CODE = BigInt(0); + const NO_ERROR_CODE = 0n; before(async function () { await initSigners(3); @@ -201,7 +201,7 @@ describe("EncryptedErrors", function () { it("cannot define errors if indexCode is greater or equal than totalNumberErrorCodes", async function () { const condition = true; - const targetErrorCode = (await this.encryptedErrors.errorGetNumCodesDefined()) + BigInt(1); + const targetErrorCode = (await this.encryptedErrors.errorGetNumCodesDefined()) + 1n; const input = this.instances.alice.createEncryptedInput(this.encryptedErrorsAddress, this.signers.alice.address); const encryptedData = await input.addBool(condition).encrypt(); @@ -242,7 +242,7 @@ describe("EncryptedErrors", function () { it("cannot change errors if indexCode is greater or equal than totalNumberErrorCodes", async function () { const condition = true; const errorCode = 1; - const targetErrorCode = (await this.encryptedErrors.errorGetNumCodesDefined()) + BigInt(1); + const targetErrorCode = (await this.encryptedErrors.errorGetNumCodesDefined()) + 1n; const input = this.instances.alice.createEncryptedInput(this.encryptedErrorsAddress, this.signers.alice.address); const encryptedData = await input.addBool(condition).add8(errorCode).encrypt();