Skip to content

Commit

Permalink
Testing WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
brickpop committed May 17, 2024
1 parent 58f90d7 commit 29556db
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 88 deletions.
5 changes: 0 additions & 5 deletions src/EmergencyMultisig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,6 @@ contract EmergencyMultisig is IEmergencyMultisig, IMembership, PluginUUPSUpgrade
/// @notice Thrown if the address list source is empty
error InvalidAddressListSource();

/// @notice Thrown if a date is out of bounds.
/// @param limit The limit value.
/// @param actual The actual value.
error DateOutOfBounds(uint64 limit, uint64 actual);

/// @notice Emitted when a proposal is created.
/// @param proposalId The ID of the proposal.
/// @param creator The creator of the proposal.
Expand Down
5 changes: 0 additions & 5 deletions src/Multisig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,6 @@ contract Multisig is IMultisig, IMembership, PluginUUPSUpgradeable, ProposalUpgr
/// @param actual The actual value.
error AddresslistLengthOutOfBounds(uint16 limit, uint256 actual);

/// @notice Thrown if a date is out of bounds.
/// @param limit The limit value.
/// @param actual The actual value.
error DateOutOfBounds(uint64 limit, uint64 actual);

/// @notice Emitted when a proposal is approve by an approver.
/// @param proposalId The ID of the proposal.
/// @param approver The approver casting the approve.
Expand Down
4 changes: 2 additions & 2 deletions src/OptimisticTokenVotingPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ contract OptimisticTokenVotingPlugin is
/// @notice Thrown if a date is out of bounds.
/// @param limit The limit value.
/// @param actual The actual value.
error DateOutOfBounds(uint64 limit, uint64 actual);
error DurationOutOfBounds(uint64 limit, uint64 actual);

/// @notice Thrown if the minimum duration value is out of bounds (less than four days or greater than 1 year).
/// @param limit The limit value.
Expand Down Expand Up @@ -333,7 +333,7 @@ contract OptimisticTokenVotingPlugin is
}

if (_duration < governanceSettings.minDuration) {
revert DateOutOfBounds({limit: governanceSettings.minDuration, actual: _duration});
revert DurationOutOfBounds({limit: governanceSettings.minDuration, actual: _duration});
}
uint64 _now = block.timestamp.toUint64();
uint64 _vetoEndDate = _now + _duration; // Since `minDuration` will be less than 1 year, `startDate + minDuration` can only overflow if the `startDate` is after `type(uint64).max - minDuration`. In this case, the proposal creation will revert and another date can be picked.
Expand Down
2 changes: 1 addition & 1 deletion test/EmergencyMultisig.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {IMembership} from "@aragon/osx/core/plugin/membership/IMembership.sol";
import {Addresslist} from "@aragon/osx/plugins/utils/Addresslist.sol";
import {DaoUnauthorized} from "@aragon/osx/core/utils/auth.sol";
import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol";
import {createProxyAndCall} from "./helpers.sol";
import {createProxyAndCall} from "./helpers/proxy.sol";

contract EmergencyMultisigTest is AragonTest {
DAO dao;
Expand Down
126 changes: 52 additions & 74 deletions test/OptimisticTokenVotingPlugin.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import {IERC1822ProxiableUpgradeable} from
import {createProxyAndCall} from "./helpers/proxy.sol";

contract OptimisticTokenVotingPluginTest is AragonTest {
DaoBuilder builder;

DAO dao;
OptimisticTokenVotingPlugin optimisticPlugin;
ERC20VotesMock votingToken;
Expand All @@ -42,9 +44,9 @@ contract OptimisticTokenVotingPluginTest is AragonTest {
event Upgraded(address indexed implementation);

function setUp() public {
vm.startPrank(alice);
switchTo(alice);

DaoBuilder builder = new DaoBuilder();
builder = new DaoBuilder();
(dao, optimisticPlugin,,, votingToken, taikoL1) = builder.build();
}

Expand Down Expand Up @@ -320,7 +322,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest {
assertEq(supported, false, "Should not support any other interface");
}

function test_GetVotingTokenReturnsTheRightAddress() public {
function test_VotingTokenReturnsTheRightAddress() public {
assertEq(address(optimisticPlugin.votingToken()), address(votingToken), "Incorrect voting token");

address oldToken = address(optimisticPlugin.votingToken());
Expand Down Expand Up @@ -352,69 +354,47 @@ contract OptimisticTokenVotingPluginTest is AragonTest {
assertEq(address(votingToken) != oldToken, true, "The token address sould have changed");
}

function test_TotalVotingPowerReturnsTheRightSupply() public {
assertEq(
optimisticPlugin.totalVotingPower(block.timestamp - 1),
votingToken.getPastTotalSupply(block.number - 1),
"Incorrect total voting power"
);
function test_TotalVotingPowerReturnsTheRightValue() public {
assertEq(optimisticPlugin.totalVotingPower(block.timestamp - 1), 10 ether, "Incorrect total voting power");
assertEq(votingToken.getPastTotalSupply(block.timestamp - 1), 10 ether, "Incorrect past supply");

// New token
votingToken = ERC20VotesMock(
createProxyAndCall(address(VOTING_TOKEN_BASE), abi.encodeCall(ERC20VotesMock.initialize, ()))
);
votingToken.mint(alice, 15 ether);
blockForward(1);
// 2
builder = new DaoBuilder();
(, optimisticPlugin,,, votingToken,) = builder.withTokenHolder(alice, 5 ether).withTokenHolder(bob, 200 ether)
.withTokenHolder(carol, 2.5 ether).build();

// Deploy a new optimisticPlugin instance
OptimisticTokenVotingPlugin.OptimisticGovernanceSettings memory settings = OptimisticTokenVotingPlugin
.OptimisticGovernanceSettings({
minVetoRatio: uint32(RATIO_BASE / 10),
minDuration: 10 days,
l2InactivityPeriod: 10 minutes,
l2AggregationGracePeriod: 2 days
});
assertEq(optimisticPlugin.totalVotingPower(block.timestamp - 1), 207.5 ether, "Incorrect total voting power");
assertEq(votingToken.getPastTotalSupply(block.timestamp - 1), 207.5 ether, "Incorrect past supply");

optimisticPlugin = OptimisticTokenVotingPlugin(
createProxyAndCall(
address(OPTIMISTIC_BASE),
abi.encodeCall(
OptimisticTokenVotingPlugin.initialize, (dao, settings, votingToken, taikoL1, taikoBridge)
)
)
);
// 2
builder = new DaoBuilder();
(, optimisticPlugin,,, votingToken,) = builder.withTokenHolder(alice, 50 ether).withTokenHolder(bob, 30 ether)
.withTokenHolder(carol, 0.1234 ether).withTokenHolder(david, 100 ether).build();

assertEq(
optimisticPlugin.totalVotingPower(block.timestamp - 1),
votingToken.getPastTotalSupply(block.number - 1),
"Incorrect total voting power"
);
assertEq(optimisticPlugin.totalVotingPower(block.timestamp - 1), 15 ether, "Incorrect total voting power");
assertEq(optimisticPlugin.totalVotingPower(block.timestamp - 1), 180.1234 ether, "Incorrect total voting power");
assertEq(votingToken.getPastTotalSupply(block.timestamp - 1), 180.1234 ether, "Incorrect past supply");
}

function test_MinVetoRatioReturnsTheRightValue() public {
assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 10), "Incorrect minVetoRatio");

// New optimisticPlugin instance
OptimisticTokenVotingPlugin.OptimisticGovernanceSettings memory settings = OptimisticTokenVotingPlugin
.OptimisticGovernanceSettings({
minVetoRatio: uint32(RATIO_BASE / 5),
minDuration: 10 days,
l2InactivityPeriod: 10 minutes,
l2AggregationGracePeriod: 2 days
});
// 2
builder = new DaoBuilder();
(, optimisticPlugin,,, votingToken,) = builder.withMinVetoRatio(1_000).build();

optimisticPlugin = OptimisticTokenVotingPlugin(
createProxyAndCall(
address(OPTIMISTIC_BASE),
abi.encodeCall(
OptimisticTokenVotingPlugin.initialize, (dao, settings, votingToken, taikoL1, taikoBridge)
)
)
);
assertEq(optimisticPlugin.minVetoRatio(), 1_000, "Incorrect minVetoRatio");

assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 5), "Incorrect minVetoRatio");
// 3
builder = new DaoBuilder();
(, optimisticPlugin,,, votingToken,) = builder.withMinVetoRatio(500_000).build();

assertEq(optimisticPlugin.minVetoRatio(), 500_000, "Incorrect minVetoRatio");

// 4
builder = new DaoBuilder();
(, optimisticPlugin,,, votingToken,) = builder.withMinVetoRatio(300_000).build();

assertEq(optimisticPlugin.minVetoRatio(), 300_000, "Incorrect minVetoRatio");
}

function test_TokenHoldersAreMembers() public {
Expand All @@ -428,7 +408,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest {
);
votingToken.mint(alice, 10 ether);
votingToken.mint(bob, 5 ether);
blockForward(1);
timeForward(1);

// Deploy a new optimisticPlugin instance
OptimisticTokenVotingPlugin.OptimisticGovernanceSettings memory settings = OptimisticTokenVotingPlugin
Expand All @@ -455,42 +435,40 @@ contract OptimisticTokenVotingPluginTest is AragonTest {

// Create proposal
function test_CreateProposalRevertsWhenCalledByANonProposer() public {
vm.stopPrank();
vm.startPrank(bob);
switchTo(alice);

IDAO.Action[] memory actions = new IDAO.Action[](0);
vm.expectRevert(
abi.encodeWithSelector(
DaoUnauthorized.selector,
address(dao),
address(optimisticPlugin),
bob,
alice,
optimisticPlugin.PROPOSER_PERMISSION_ID()
)
);
optimisticPlugin.createProposal("", actions, 0, 0);

vm.stopPrank();
vm.startPrank(alice);

dao.grant(address(optimisticPlugin), alice, optimisticPlugin.PROPOSER_PERMISSION_ID());
optimisticPlugin.createProposal("", actions, 0, 0);
}

function test_CreateProposalSucceedsWhenMinimumVotingPowerIsZero() public {
// Bob can create proposals on the optimisticPlugin now
dao.grant(address(optimisticPlugin), bob, optimisticPlugin.PROPOSER_PERMISSION_ID());
undoSwitch();
switchTo(bob);

vm.stopPrank();
vm.startPrank(bob);

IDAO.Action[] memory actions = new IDAO.Action[](0);
uint256 proposalId1 = optimisticPlugin.createProposal("", actions, 0, 0);
uint256 proposalId2 = optimisticPlugin.createProposal("", actions, 0, 0);
assertEq(proposalId1 + 1, proposalId2, "Should be +1");
vm.expectRevert(
abi.encodeWithSelector(
DaoUnauthorized.selector,
address(dao),
address(optimisticPlugin),
bob,
optimisticPlugin.PROPOSER_PERMISSION_ID()
)
);
optimisticPlugin.createProposal("", actions, 0, 0);
}

function test_CreateProposalRevertsIfThereIsNoVotingPower() public {
vm.stopPrank();
vm.startPrank(alice);
switchTo(alice);

// Deploy ERC20 token (0 supply)
votingToken = ERC20VotesMock(
Expand Down
8 changes: 7 additions & 1 deletion test/helpers/DaoBuilder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ contract DaoBuilder is Test {

TaikoL1Status public taikoL1Status = TaikoL1Status.Standard;
address[] public multisigMembers;
address[] public optimisticProposers;
MintEntry[] public tokenHolders;

uint32 public minVetoRatio = uint32(RATIO_BASE / 10); // 10%
uint64 public minDuration = 4 days;
uint64 public minDuration = 0;
uint64 public l2InactivityPeriod = 10 minutes;
uint64 public l2AggregationGracePeriod = 2 days;

Expand Down Expand Up @@ -103,6 +104,11 @@ contract DaoBuilder is Test {
return this;
}

function withProposerOnOptimistic(address newProposer) public returns (DaoBuilder) {
optimisticProposers.push(newProposer);
return this;
}

function withMinApprovals(uint16 newMinApprovals) public returns (DaoBuilder) {
if (newMinApprovals > multisigMembers.length) revert("You should add enough multisig members first");
minApprovals = newMinApprovals;
Expand Down

0 comments on commit 29556db

Please sign in to comment.