Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit tests for governance #54

Merged
merged 16 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions ethereum/contracts/dev-contracts/EventOnFallback.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract EventOnFallback {
event Called(address msgSender, uint256 value, bytes data);

fallback() external payable {
emit Called(msg.sender, msg.value, msg.data);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {GovernanceTest} from "./_Governance_Shared.t.sol";
import {IGovernance} from "../../../../../cache/solpp-generated-contracts/governance/IGovernance.sol";

contract Authorization is GovernanceTest {
function test_RevertWhen_SchedulingByUnauthorisedAddress() public {
vm.prank(randomSigner);
vm.expectRevert(bytes("Ownable: caller is not the owner"));
IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(address(eventOnFallback), 0, "");
governance.scheduleTransparent(op, 0);
}

function test_RevertWhen_SchedulingBySecurityCouncil() public {
vm.prank(securityCouncil);
vm.expectRevert(bytes("Ownable: caller is not the owner"));
IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(address(eventOnFallback), 0, "");
governance.scheduleTransparent(op, 0);
}

function test_RevertWhen_SchedulingShadowByUnauthorisedAddress() public {
vm.prank(randomSigner);
vm.expectRevert(bytes("Ownable: caller is not the owner"));
governance.scheduleShadow(bytes32(0), 0);
}

function test_RevertWhen_SchedulingShadowBySecurityCouncil() public {
vm.prank(securityCouncil);
vm.expectRevert(bytes("Ownable: caller is not the owner"));
governance.scheduleShadow(bytes32(0), 0);
}

function test_RevertWhen_ExecutingByUnauthorisedAddress() public {
vm.prank(randomSigner);
vm.expectRevert(bytes("Only the owner and security council are allowed to call this function"));
IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(address(eventOnFallback), 0, "");
governance.execute(op);
}

function test_RevertWhen_ExecutingInstantByUnauthorisedAddress() public {
vm.prank(randomSigner);
vm.expectRevert(bytes("Only security council allowed to call this function"));
IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(address(eventOnFallback), 0, "");
governance.executeInstant(op);
}

function test_RevertWhen_ExecutingInstantByOwner() public {
vm.prank(owner);
vm.expectRevert(bytes("Only security council allowed to call this function"));
IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(address(eventOnFallback), 0, "");
governance.executeInstant(op);
}

function test_RevertWhen_CancelByUnauthorisedAddress() public {
vm.prank(randomSigner);
vm.expectRevert(bytes("Only the owner and security council are allowed to call this function"));
governance.cancel(bytes32(0));
}

function test_RevertWhen_UpdateDelayByUnauthorisedAddress() public {
vm.prank(randomSigner);
vm.expectRevert(bytes("Only governance contract itself allowed to call this function"));
governance.updateDelay(0);
}

function test_RevertWhen_UpdateDelayByOwner() public {
vm.prank(owner);
vm.expectRevert(bytes("Only governance contract itself allowed to call this function"));
governance.updateDelay(0);
}

function test_RevertWhen_UpdateDelayBySecurityCouncil() public {
vm.prank(securityCouncil);
vm.expectRevert(bytes("Only governance contract itself allowed to call this function"));
governance.updateDelay(0);
}

function test_RevertWhen_UpdateSecurityCouncilByUnauthorisedAddress() public {
vm.prank(randomSigner);
vm.expectRevert(bytes("Only governance contract itself allowed to call this function"));
governance.updateSecurityCouncil(address(0));
}

function test_RevertWhen_UpdateSecurityCouncilByOwner() public {
vm.prank(owner);
vm.expectRevert(bytes("Only governance contract itself allowed to call this function"));
governance.updateSecurityCouncil(address(0));
}

function test_RevertWhen_UpdateSecurityCouncilBySecurityCouncil() public {
vm.prank(owner);
vladbochok marked this conversation as resolved.
Show resolved Hide resolved
vm.expectRevert(bytes("Only governance contract itself allowed to call this function"));
governance.updateSecurityCouncil(address(0));
}
}
225 changes: 225 additions & 0 deletions ethereum/test/foundry/unit/concrete/Governance/Executing.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {GovernanceTest} from "./_Governance_Shared.t.sol";
import {Utils} from "../Utils/Utils.sol";
import {IGovernance} from "../../../../../cache/solpp-generated-contracts/governance/IGovernance.sol";

contract ExecutingTest is GovernanceTest {
function test_ScheduleTransparentAndExecute() public {
vm.startPrank(owner);

IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(address(eventOnFallback), 0, "");
governance.scheduleTransparent(op, 1000);
vm.warp(block.timestamp + 1000);
executeOpAndCheck(op);
}

function test_ScheduleTransparentAndExecuteInstant() public {
IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(address(eventOnFallback), 0, "");
vm.prank(owner);
governance.scheduleTransparent(op, 1000000);
vm.prank(securityCouncil);
executeInstantOpAndCheck(op);
}

function test_ScheduleShadowAndExecute() public {
IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(address(eventOnFallback), 0, "");
bytes32 opId = governance.hashOperation(op);
vm.startPrank(owner);
governance.scheduleShadow(opId, 100000);
vm.warp(block.timestamp + 100001);
vladbochok marked this conversation as resolved.
Show resolved Hide resolved
vm.startPrank(securityCouncil);
executeOpAndCheck(op);
}

function test_ScheduleShadowAndExecuteInstant() public {
IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(address(eventOnFallback), 0, "");
bytes32 opId = governance.hashOperation(op);
vm.startPrank(owner);
governance.scheduleShadow(opId, 100000);
vm.startPrank(securityCouncil);
executeInstantOpAndCheck(op);
}

function test_RevertWhen_ExecutingOperationBeforeDeadline() public {
vm.startPrank(owner);
IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(address(eventOnFallback), 0, "");
governance.scheduleTransparent(op, 10000);
vm.expectRevert(bytes("Operation must be ready before execution"));
governance.execute(op);
}

function test_RevertWhen_ExecutingOperationWithDifferentTarget() public {
vm.startPrank(owner);
IGovernance.Operation memory validOp = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
""
);
governance.scheduleTransparent(validOp, 0);

IGovernance.Operation memory invalidOp = operationWithOneCallZeroSaltAndPredecessor(address(0), 0, "");
vm.expectRevert(bytes("Operation must be ready before execution"));
governance.execute(invalidOp);
}

function test_RevertWhen_ExecutingOperationWithDifferentValue() public {
vm.startPrank(owner);
IGovernance.Operation memory validOp = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
""
);
governance.scheduleTransparent(validOp, 0);

IGovernance.Operation memory invalidOp = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
1,
""
);
vm.expectRevert(bytes("Operation must be ready before execution"));
governance.execute(invalidOp);
}

function test_RevertWhen_ExecutingOperationWithDifferentData() public {
vm.startPrank(owner);
IGovernance.Operation memory validOp = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
""
);
governance.scheduleTransparent(validOp, 0);

IGovernance.Operation memory invalidOp = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
"00"
);
vm.expectRevert(bytes("Operation must be ready before execution"));
governance.execute(invalidOp);
}

function test_RevertWhen_ExecutingOperationWithDifferentPredecessor() public {
vm.startPrank(owner);
// Executing one operation to get a valid executed predecessor
IGovernance.Operation memory executedOp = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
"1122"
);
governance.scheduleTransparent(executedOp, 0);
executeOpAndCheck(executedOp);

// Schedule & execute operation with 0 predecessor
IGovernance.Operation memory validOp = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
""
);
governance.scheduleTransparent(validOp, 0);
executeOpAndCheck(validOp);

// Schedule operation with predecessor of `executedOp` operation
IGovernance.Operation memory invalidOp = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
""
);
invalidOp.predecessor = governance.hashOperation(executedOp);

// Failed to execute operation that wasn't scheduled
vm.expectRevert(bytes("Operation must be ready before execution"));
governance.execute(invalidOp);
vladbochok marked this conversation as resolved.
Show resolved Hide resolved
}

function test_RevertWhen_ExecutingOperationWithDifferentSalt() public {
vm.startPrank(owner);
IGovernance.Operation memory validOp = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
""
);
governance.scheduleTransparent(validOp, 0);

IGovernance.Operation memory invalidOp = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
""
);
invalidOp.salt = Utils.randomBytes32("wrongSalt");
vm.expectRevert(bytes("Operation must be ready before execution"));
governance.execute(invalidOp);
}

function test_RevertWhen_ExecutingOperationWithNonExecutedPredecessor() public {
vm.startPrank(owner);

IGovernance.Operation memory invalidOp = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
"1122"
);
invalidOp.predecessor = Utils.randomBytes32("randomPredecessor");
governance.scheduleTransparent(invalidOp, 0);
vm.expectRevert(bytes("Predecessor operation not completed"));
governance.execute(invalidOp);
}

function test_RevertWhen_ScheduleOperationOnceAndExecuteTwice() public {
vm.startPrank(owner);

IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
"1122"
);
governance.scheduleTransparent(op, 0);
executeOpAndCheck(op);

vm.expectRevert(bytes("Operation must be ready before execution"));
governance.execute(op);
}

function test_RevertWhen_ExecutingOperationAfterCanceling() public {
vm.startPrank(owner);

IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
"1122"
);
governance.scheduleTransparent(op, 0);
governance.cancel(governance.hashOperation(op));
vm.expectRevert(bytes("Operation must be ready before execution"));
governance.execute(op);
}

function test_ExecutingOperationAfterRescheduling() public {
vm.startPrank(owner);

IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
"1122"
);
governance.scheduleTransparent(op, 0);
governance.cancel(governance.hashOperation(op));
governance.scheduleTransparent(op, 0);
executeOpAndCheck(op);
}

function test_RevertWhen_ExecutingOperationTwice() public {
vm.startPrank(owner);

IGovernance.Operation memory op = operationWithOneCallZeroSaltAndPredecessor(
address(eventOnFallback),
0,
"1122"
);
governance.scheduleTransparent(op, 0);
executeOpAndCheck(op);
vm.expectRevert(bytes("Operation with this proposal id already exists"));
governance.scheduleTransparent(op, 0);
}
}
Loading
Loading