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

Encryption registry for smart wallets #40

Merged
merged 45 commits into from
Nov 29, 2024
Merged
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
e02aa0b
Encryption registry
brickpop Oct 14, 2024
ee6b449
Encryption registry with partial tests
brickpop Oct 14, 2024
3d51a8e
Tests WIP
brickpop Oct 14, 2024
cebb7a5
Encryption registry tests ok
brickpop Oct 14, 2024
1b8cfac
Final touches
brickpop Oct 15, 2024
056d02f
Deployment info
brickpop Oct 17, 2024
91613c2
WIP: Swapping the address list source to the emergency multisig
brickpop Oct 17, 2024
0cf968d
WIP: Splitting the address list into a separate contract, abstracting…
brickpop Oct 18, 2024
fff9944
Factory and setup adaptations
brickpop Oct 21, 2024
a275b20
Testing WIP
brickpop Oct 22, 2024
b5353ae
Work in progress
brickpop Oct 22, 2024
1332f2d
Defining the signer list tests
brickpop Oct 24, 2024
f375c15
New tests definition WIP
brickpop Oct 24, 2024
aa5d023
Test tree
brickpop Oct 24, 2024
338f31e
Definig the multisig test branches
brickpop Oct 25, 2024
adb0993
Emergency multisig test definition
brickpop Oct 25, 2024
5f06467
Test definitions ready
brickpop Oct 25, 2024
ffc85eb
Test definition ready
brickpop Oct 25, 2024
3155f3f
Clearer names
brickpop Oct 25, 2024
bb04d32
Minor edits
brickpop Nov 5, 2024
6a804fd
Signer List tests WIP
brickpop Nov 6, 2024
6d56831
SignerList tree tests
brickpop Nov 6, 2024
0a261c6
SignerList tests
brickpop Nov 6, 2024
0188026
Signer List tests ready
brickpop Nov 7, 2024
6b42038
DAO Factory and tests updated
brickpop Nov 7, 2024
faf711c
Adapted emergency plugin setup and factory
brickpop Nov 7, 2024
225fc81
Adapted tests WIP
brickpop Nov 7, 2024
8bca1d1
Encryption registry changes
brickpop Nov 7, 2024
52c8e20
Multisigs WIP
brickpop Nov 8, 2024
e4abfec
Multisig tests WIP
brickpop Nov 8, 2024
d3e91e2
Multisig testing refactor WIP
brickpop Nov 8, 2024
6adf49e
Multisig's testing WIP
brickpop Nov 8, 2024
a0e3ae2
Optimizing the signer list getters
brickpop Nov 12, 2024
413c70c
Adapted tests (owner at block)
brickpop Nov 12, 2024
927079d
Improved interfaces and tests
brickpop Nov 12, 2024
cd2970d
Emergency multisig tests ready
brickpop Nov 12, 2024
ed42c4a
Multisig test tree WIP
brickpop Nov 13, 2024
9a70bc7
Tests running clean
brickpop Nov 14, 2024
f12b40e
Tests running clean
brickpop Nov 14, 2024
601efd2
Final touches
brickpop Nov 14, 2024
c837b87
Renaming test files
brickpop Nov 14, 2024
702c38e
Showing the signer list on deploy
brickpop Nov 14, 2024
324ecc8
Ensuring that self appointing resets the appointed address
brickpop Nov 22, 2024
6b3bfd1
Clearer fuzz test values to skip
brickpop Nov 22, 2024
a49b8ff
Amendment
brickpop Nov 26, 2024
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
Prev Previous commit
Next Next commit
Multisig testing refactor WIP
brickpop committed Nov 8, 2024
commit d3e91e2d0cca0862dd3fb862a56ee03b977042bb
232 changes: 209 additions & 23 deletions test/EmergencyMultisigTree.t.sol
Original file line number Diff line number Diff line change
@@ -5,7 +5,12 @@ import {AragonTest} from "./base/AragonTest.sol";
import {Addresslist} from "@aragon/osx/plugins/utils/Addresslist.sol";
import {EmergencyMultisig} from "../src/EmergencyMultisig.sol";
import {OptimisticTokenVotingPlugin} from "../src/OptimisticTokenVotingPlugin.sol";
import {SignerList, UPDATE_SIGNER_LIST_PERMISSION_ID} from "../src/SignerList.sol";
import {
SignerList,
UPDATE_SIGNER_LIST_PERMISSION_ID,
UPDATE_SIGNER_LIST_SETTINGS_PERMISSION_ID
} from "../src/SignerList.sol";
import {EncryptionRegistry} from "../src/EncryptionRegistry.sol";
import {DaoBuilder} from "./helpers/DaoBuilder.sol";
import {DAO} from "@aragon/osx/core/dao/DAO.sol";
import {IDAO} from "@aragon/osx/core/dao/IDAO.sol";
@@ -18,11 +23,12 @@ import {IEmergencyMultisig} from "../src/interfaces/IEmergencyMultisig.sol";
uint64 constant EMERGENCY_MULTISIG_PROPOSAL_EXPIRATION_PERIOD = 10 days;

contract EmergencyMultisigTest is AragonTest {
SignerList signerList;
DaoBuilder builder;
DAO dao;
EmergencyMultisig eMultisig;
OptimisticTokenVotingPlugin optimisticPlugin;
SignerList signerList;
EncryptionRegistry encryptionRegistry;

address immutable SIGNER_LIST_BASE = address(new SignerList());

@@ -57,9 +63,8 @@ contract EmergencyMultisigTest is AragonTest {
vm.roll(100);

builder = new DaoBuilder();
(dao,,, eMultisig,, signerList,,) = builder.withMultisigMember(alice).withMultisigMember(bob).withMultisigMember(
carol
).withMultisigMember(david).withMinApprovals(3).build();
(dao,,, eMultisig,, signerList, encryptionRegistry,) = builder.withMultisigMember(alice).withMultisigMember(bob)
.withMultisigMember(carol).withMultisigMember(david).withMinApprovals(3).build();
}

modifier givenANewlyDeployedContract() {
@@ -897,7 +902,18 @@ contract EmergencyMultisigTest is AragonTest {

function test_GivenOnlyListedIsFalse() external whenCallingCreateProposal {
// It allows anyone to create
vm.skip(true);

// Deploy a new instance with custom settings
(dao, optimisticPlugin,, eMultisig,,,,) = builder.withoutOnlyListed().build();

vm.startPrank(randomWallet);
eMultisig.createProposal("", 0, 0, optimisticPlugin, false);

vm.startPrank(address(0x1234));
eMultisig.createProposal("", 0, 0, optimisticPlugin, false);

vm.startPrank(address(0x22345));
eMultisig.createProposal("", 0, 0, optimisticPlugin, false);
}

modifier givenOnlyListedIsTrue() {
@@ -910,7 +926,31 @@ contract EmergencyMultisigTest is AragonTest {
givenOnlyListedIsTrue
{
// It reverts
vm.skip(true);

dao.grant(address(signerList), alice, UPDATE_SIGNER_LIST_PERMISSION_ID);
dao.grant(address(signerList), alice, UPDATE_SIGNER_LIST_SETTINGS_PERMISSION_ID);
signerList.updateSettings(SignerList.Settings(encryptionRegistry, 3));

vm.startPrank(randomWallet);
vm.expectRevert(abi.encodeWithSelector(EmergencyMultisig.ProposalCreationForbidden.selector, randomWallet));
eMultisig.createProposal("", 0, 0, optimisticPlugin, false);

// 2
vm.startPrank(taikoBridge);
vm.expectRevert(abi.encodeWithSelector(EmergencyMultisig.ProposalCreationForbidden.selector, taikoBridge));
eMultisig.createProposal("", 0, 0, optimisticPlugin, false);

// It reverts if listed before but not now

vm.startPrank(alice);
dao.grant(address(signerList), alice, UPDATE_SIGNER_LIST_PERMISSION_ID);

address[] memory addrs = new address[](1);
addrs[0] = alice;
signerList.removeSigners(addrs);

vm.expectRevert(abi.encodeWithSelector(EmergencyMultisig.ProposalCreationForbidden.selector, alice));
eMultisig.createProposal("", 0, 0, optimisticPlugin, false);
}

function test_GivenCreationCallerIsAppointedByAFormerSigner()
@@ -919,7 +959,26 @@ contract EmergencyMultisigTest is AragonTest {
givenOnlyListedIsTrue
{
// It reverts
vm.skip(true);

encryptionRegistry.appointWallet(randomWallet);
dao.grant(address(signerList), alice, UPDATE_SIGNER_LIST_PERMISSION_ID);
dao.grant(address(signerList), alice, UPDATE_SIGNER_LIST_SETTINGS_PERMISSION_ID);
signerList.updateSettings(SignerList.Settings(encryptionRegistry, 3));

address[] memory addrs = new address[](1);
addrs[0] = alice;
signerList.removeSigners(addrs);

vm.startPrank(randomWallet);
vm.expectRevert(abi.encodeWithSelector(EmergencyMultisig.ProposalCreationForbidden.selector, randomWallet));
eMultisig.createProposal("", 0, 0, optimisticPlugin, false);

// Undo
vm.startPrank(alice);
signerList.addSigners(addrs);

vm.startPrank(randomWallet);
eMultisig.createProposal("", 0, 0, optimisticPlugin, false);
}

function test_GivenCreationCallerIsListedAndSelfAppointed()
@@ -928,7 +987,18 @@ contract EmergencyMultisigTest is AragonTest {
givenOnlyListedIsTrue
{
// It creates the proposal
vm.skip(true);

vm.startPrank(alice);
eMultisig.createProposal("a", 0, 0, optimisticPlugin, false);

vm.startPrank(bob);
eMultisig.createProposal("b", 0, 0, optimisticPlugin, false);

vm.startPrank(carol);
eMultisig.createProposal("c", 0, 0, optimisticPlugin, true);

vm.startPrank(david);
eMultisig.createProposal("d", 0, 0, optimisticPlugin, false);
}

function test_GivenCreationCallerIsListedAppointingSomeoneElseNow()
@@ -937,7 +1007,22 @@ contract EmergencyMultisigTest is AragonTest {
givenOnlyListedIsTrue
{
// It creates the proposal
vm.skip(true);

vm.startPrank(alice);
encryptionRegistry.appointWallet(address(0x1234));
eMultisig.createProposal("a", 0, 0, optimisticPlugin, false);

vm.startPrank(bob);
encryptionRegistry.appointWallet(address(0x2345));
eMultisig.createProposal("b", 0, 0, optimisticPlugin, false);

vm.startPrank(carol);
encryptionRegistry.appointWallet(address(0x3456));
eMultisig.createProposal("c", 0, 0, optimisticPlugin, false);

vm.startPrank(david);
encryptionRegistry.appointWallet(address(0x4567));
eMultisig.createProposal("d", 0, 0, optimisticPlugin, false);
}

function test_GivenCreationCallerIsAppointedByACurrentSigner()
@@ -946,33 +1031,134 @@ contract EmergencyMultisigTest is AragonTest {
givenOnlyListedIsTrue
{
// It creates the proposal
vm.skip(true);

vm.startPrank(alice);
encryptionRegistry.appointWallet(address(0x1234));
vm.startPrank(address(0x1234));
eMultisig.createProposal("a", 0, 0, optimisticPlugin, false);

vm.startPrank(bob);
encryptionRegistry.appointWallet(address(0x2345));
vm.startPrank(address(0x2345));
eMultisig.createProposal("b", 0, 0, optimisticPlugin, false);

vm.startPrank(carol);
encryptionRegistry.appointWallet(address(0x3456));
vm.startPrank(address(0x3456));
eMultisig.createProposal("c", 0, 0, optimisticPlugin, false);

vm.startPrank(david);
encryptionRegistry.appointWallet(address(0x4567));
vm.startPrank(address(0x4567));
eMultisig.createProposal("d", 0, 0, optimisticPlugin, false);
}

function test_GivenApproveProposalIsTrue() external whenCallingCreateProposal {
uint256 pid;
uint256 approvals;

// It creates and calls approval in one go
vm.skip(true);

vm.startPrank(alice);
pid = eMultisig.createProposal("a", 0, 0, optimisticPlugin, true);
(, approvals,,,,,) = eMultisig.getProposal(pid);
assertEq(approvals, 1, "Should be 1");

vm.startPrank(bob);
pid = eMultisig.createProposal("b", 0, 0, optimisticPlugin, true);
(, approvals,,,,,) = eMultisig.getProposal(pid);
assertEq(approvals, 1, "Should be 1");
}

function test_GivenApproveProposalIsFalse() external whenCallingCreateProposal {
uint256 pid;
uint256 approvals;

// It only creates the proposal
vm.skip(true);

vm.startPrank(alice);
pid = eMultisig.createProposal("a", 0, 0, optimisticPlugin, true);
(, approvals,,,,,) = eMultisig.getProposal(pid);
assertEq(approvals, 1, "Should be 1");

vm.startPrank(bob);
pid = eMultisig.createProposal("b", 0, 0, optimisticPlugin, true);
(, approvals,,,,,) = eMultisig.getProposal(pid);
assertEq(approvals, 1, "Should be 1");

vm.startPrank(carol);
pid = eMultisig.createProposal("c", 0, 0, optimisticPlugin, false);
(, approvals,,,,,) = eMultisig.getProposal(pid);
assertEq(approvals, 0, "Should be 0");

vm.startPrank(david);
pid = eMultisig.createProposal("d", 0, 0, optimisticPlugin, false);
(, approvals,,,,,) = eMultisig.getProposal(pid);
assertEq(approvals, 0, "Should be 0");
}

function test_WhenCallingHashActions() external {
bytes32 hashedActions;
IDAO.Action[] memory actions = new IDAO.Action[](0);

// It returns the right result
// It reacts to any of the values changing
// It same input produces the same output
vm.skip(true);

hashedActions = eMultisig.hashActions(actions);
assertEq(hashedActions, hex"569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd");

actions = new IDAO.Action[](1);
actions[0] = IDAO.Action(address(0), 0, bytes(string("")));
hashedActions = eMultisig.hashActions(actions);
assertEq(hashedActions, hex"7cde746dfbb8dfd7721b5995769f873e3ff50416302673a354990b553bb0e208");

actions = new IDAO.Action[](1);
actions[0] = IDAO.Action(bob, 1 ether, bytes(string("")));
hashedActions = eMultisig.hashActions(actions);
assertEq(hashedActions, hex"e212a57e4595f81151b46333ea31e2d5043b53bd562141e1efa1b2778cb3c208");

actions = new IDAO.Action[](2);
actions[0] = IDAO.Action(bob, 1 ether, bytes(string("")));
actions[1] = IDAO.Action(carol, 2 ether, bytes(string("data")));
hashedActions = eMultisig.hashActions(actions);
assertEq(hashedActions, hex"4be399aee320511a56f584fae21b92c78f47bff143ec3965b7d911776d39bc7d");
}

modifier givenTheProposalIsNotCreated() {
_;
}

function test_WhenCallingGetProposalBeingUncreated() external givenTheProposalIsNotCreated {
function test_WhenCallingGetProposalBeingUncreated() external view givenTheProposalIsNotCreated {
// It should return empty values
vm.skip(true);
uint256 pid;
bool executed;
uint16 approvals;
EmergencyMultisig.ProposalParameters memory parameters;
bytes memory encryptedPayloadURI;
bytes32 publicMetadataUriHash;
bytes32 destinationActionsHash;
OptimisticTokenVotingPlugin destinationPlugin;

(
executed,
approvals,
parameters,
encryptedPayloadURI,
publicMetadataUriHash,
destinationActionsHash,
destinationPlugin
) = eMultisig.getProposal(pid);

assertEq(executed, false, "Should be false");
assertEq(approvals, 0, "Should be 0");
assertEq(parameters.minApprovals, 0, "Incorrect minApprovals");
assertEq(parameters.snapshotBlock, 0, "Incorrect snapshotBlock");
assertEq(parameters.expirationDate, 0, "Incorrect expirationDate");
assertEq(encryptedPayloadURI, "", "Incorrect encryptedPayloadURI");
assertEq(publicMetadataUriHash, bytes32(0), "Incorrect publicMetadataUriHash");
assertEq(destinationActionsHash, bytes32(0), "Incorrect destinationActionsHash");
assertEq(address(destinationPlugin), address(0), "Incorrect destinationPlugin");
}

function test_WhenCallingCanApproveAndApproveBeingUncreated() external givenTheProposalIsNotCreated {
@@ -992,7 +1178,7 @@ contract EmergencyMultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingUncreated() external givenTheProposalIsNotCreated {
function test_WhenCallingCanExecuteOrExecuteBeingUncreated() external givenTheProposalIsNotCreated {
// It canExecute should always return false
vm.skip(true);
}
@@ -1025,7 +1211,7 @@ contract EmergencyMultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingOpen() external givenTheProposalIsOpen {
function test_WhenCallingCanExecuteOrExecuteBeingOpen() external givenTheProposalIsOpen {
// It canExecute should return false (when listed on creation, self appointed now)
// It execute should revert (when listed on creation, self appointed now)
// It canExecute should return false (when listed on creation, appointing someone else now)
@@ -1059,7 +1245,7 @@ contract EmergencyMultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingApproved() external givenTheProposalWasApprovedByTheAddress {
function test_WhenCallingCanExecuteOrExecuteBeingApproved() external givenTheProposalWasApprovedByTheAddress {
// It canExecute should return false (when listed on creation, self appointed now)
// It execute should revert (when listed on creation, self appointed now)
// It canExecute should return false (when currently appointed by a signer listed on creation)
@@ -1093,14 +1279,14 @@ contract EmergencyMultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteWithModifiedDataBeingPassed() external givenTheProposalPassed {
function test_WhenCallingCanExecuteOrExecuteWithModifiedDataBeingPassed() external givenTheProposalPassed {
// It execute should revert with modified metadata
// It execute should revert with modified actions
// It execute should work with matching data
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingPassed() external givenTheProposalPassed {
function test_WhenCallingCanExecuteOrExecuteBeingPassed() external givenTheProposalPassed {
// It canExecute should return true, always
// It execute should work, when called by anyone with the actions
// It execute should emit an event, when called by anyone with the actions
@@ -1142,7 +1328,7 @@ contract EmergencyMultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingExecuted() external givenTheProposalIsAlreadyExecuted {
function test_WhenCallingCanExecuteOrExecuteBeingExecuted() external givenTheProposalIsAlreadyExecuted {
// It canExecute should return false (when listed on creation, self appointed now)
// It execute should revert (when listed on creation, self appointed now)
// It canExecute should return false (when listed on creation, appointing someone else now)
@@ -1180,7 +1366,7 @@ contract EmergencyMultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingExpired() external givenTheProposalExpired {
function test_WhenCallingCanExecuteOrExecuteBeingExpired() external givenTheProposalExpired {
// It canExecute should return false (when listed on creation, self appointed now)
// It execute should revert (when listed on creation, self appointed now)
// It canExecute should return false (when listed on creation, appointing someone else now)
28 changes: 14 additions & 14 deletions test/EmergencyMultisigTree.t.yaml
Original file line number Diff line number Diff line change
@@ -93,6 +93,7 @@ EmergencyMultisigTest:
- given: creation caller is not listed or appointed
then:
- it: reverts
- it: reverts if listed before but not now
- given: creation caller is appointed by a former signer
then:
- it: reverts
@@ -127,7 +128,7 @@ EmergencyMultisigTest:
then:
- it: should return empty values
# Approval
- when: calling canApprove and approve [being uncreated]
- when: calling canApprove or approve [being uncreated]
then:
- it: canApprove should return false (when currently listed and self appointed)
- it: approve should revert (when currently listed and self appointed)
@@ -142,7 +143,7 @@ EmergencyMultisigTest:
then:
- it: hasApproved should always return false
# Execution
- when: calling canExecute and execute [being uncreated]
- when: calling canExecute or execute [being uncreated]
then:
- it: canExecute should always return false

@@ -153,7 +154,7 @@ EmergencyMultisigTest:
then:
- it: should return the right values
# Approval
- when: calling canApprove and approve [being open]
- when: calling canApprove or approve [being open]
then:
- it: canApprove should return true (when listed on creation, self appointed now)
- it: approve should work (when listed on creation, self appointed now)
@@ -171,7 +172,7 @@ EmergencyMultisigTest:
then:
- it: hasApproved should return false until approved
# Execution
- when: calling canExecute and execute [being open]
- when: calling canExecute or execute [being open]
then:
- it: canExecute should return false (when listed on creation, self appointed now)
- it: execute should revert (when listed on creation, self appointed now)
@@ -189,7 +190,7 @@ EmergencyMultisigTest:
then:
- it: should return the right values
# Approval
- when: calling canApprove and approve [being approved]
- when: calling canApprove or approve [being approved]
then:
- it: canApprove should return false (when listed on creation, self appointed now)
- it: approve should revert (when listed on creation, self appointed now)
@@ -204,7 +205,7 @@ EmergencyMultisigTest:
then:
- it: hasApproved should return false until approved
# Execution
- when: calling canExecute and execute [being approved]
- when: calling canExecute or execute [being approved]
then:
- it: canExecute should return false (when listed on creation, self appointed now)
- it: execute should revert (when listed on creation, self appointed now)
@@ -222,7 +223,7 @@ EmergencyMultisigTest:
then:
- it: should return the right values
# Approval
- when: calling canApprove and approve [being passed]
- when: calling canApprove or approve [being passed]
then:
- it: canApprove should return false (when listed on creation, self appointed now)
- it: approve should revert (when listed on creation, self appointed now)
@@ -237,13 +238,13 @@ EmergencyMultisigTest:
then:
- it: hasApproved should return false until approved
# Execution integrity
- when: calling canExecute and execute with modified data [being passed]
- when: calling canExecute or execute with modified data [being passed]
then:
- it: execute should revert with modified metadata
- it: execute should revert with modified actions
- it: execute should work with matching data
# Execution
- when: calling canExecute and execute [being passed]
- when: calling canExecute or execute [being passed]
then:
- it: canExecute should return true, always
- it: execute should work, when called by anyone with the actions
@@ -264,7 +265,7 @@ EmergencyMultisigTest:
then:
- it: should return the right values
# Approval
- when: calling canApprove and approve [being executed]
- when: calling canApprove or approve [being executed]
then:
- it: canApprove should return false (when listed on creation, self appointed now)
- it: approve should revert (when listed on creation, self appointed now)
@@ -279,7 +280,7 @@ EmergencyMultisigTest:
then:
- it: hasApproved should return false until approved
# Execution
- when: calling canExecute and execute [being executed]
- when: calling canExecute or execute [being executed]
then:
- it: canExecute should return false (when listed on creation, self appointed now)
- it: execute should revert (when listed on creation, self appointed now)
@@ -297,7 +298,7 @@ EmergencyMultisigTest:
then:
- it: should return the right values
# Approval
- when: calling canApprove and approve [being expired]
- when: calling canApprove or approve [being expired]
then:
- it: canApprove should return false (when listed on creation, self appointed now)
- it: approve should revert (when listed on creation, self appointed now)
@@ -312,7 +313,7 @@ EmergencyMultisigTest:
then:
- it: hasApproved should return false until approved
# Execution
- when: calling canExecute and execute [being expired]
- when: calling canExecute or execute [being expired]
then:
- it: canExecute should return false (when listed on creation, self appointed now)
- it: execute should revert (when listed on creation, self appointed now)
@@ -322,4 +323,3 @@ EmergencyMultisigTest:
- it: execute should revert (when currently appointed by a signer listed on creation)
- it: canExecute should return false (when unlisted on creation, unappointed now)
- it: execute should revert (when unlisted on creation, unappointed now)

196 changes: 175 additions & 21 deletions test/MultisigTree.t.sol
Original file line number Diff line number Diff line change
@@ -5,7 +5,12 @@ import {AragonTest} from "./base/AragonTest.sol";
import {Addresslist} from "@aragon/osx/plugins/utils/Addresslist.sol";
import {Multisig} from "../src/Multisig.sol";
import {OptimisticTokenVotingPlugin} from "../src/OptimisticTokenVotingPlugin.sol";
import {SignerList, UPDATE_SIGNER_LIST_PERMISSION_ID} from "../src/SignerList.sol";
import {
SignerList,
UPDATE_SIGNER_LIST_PERMISSION_ID,
UPDATE_SIGNER_LIST_SETTINGS_PERMISSION_ID
} from "../src/SignerList.sol";
import {EncryptionRegistry} from "../src/EncryptionRegistry.sol";
import {DaoBuilder} from "./helpers/DaoBuilder.sol";
import {DAO} from "@aragon/osx/core/dao/DAO.sol";
import {IDAO} from "@aragon/osx/core/dao/IDAO.sol";
@@ -18,11 +23,12 @@ import {IMultisig} from "../src/interfaces/IMultisig.sol";
uint64 constant MULTISIG_PROPOSAL_EXPIRATION_PERIOD = 10 days;

contract MultisigTest is AragonTest {
SignerList signerList;
DaoBuilder builder;
DAO dao;
Multisig multisig;
OptimisticTokenVotingPlugin optimisticPlugin;
SignerList signerList;
EncryptionRegistry encryptionRegistry;

address immutable SIGNER_LIST_BASE = address(new SignerList());

@@ -58,9 +64,8 @@ contract MultisigTest is AragonTest {
vm.startPrank(alice);

builder = new DaoBuilder();
(dao,, multisig,,, signerList,,) = builder.withMultisigMember(alice).withMultisigMember(bob).withMultisigMember(
carol
).withMultisigMember(david).withMinApprovals(3).build();
(dao,, multisig,,, signerList, encryptionRegistry,) = builder.withMultisigMember(alice).withMultisigMember(bob)
.withMultisigMember(carol).withMultisigMember(david).withMinApprovals(3).build();
}

modifier givenANewlyDeployedContract() {
@@ -894,7 +899,14 @@ contract MultisigTest is AragonTest {

function test_GivenOnlyListedIsFalse() external whenCallingCreateProposal {
// It allows anyone to create
vm.skip(true);

builder = new DaoBuilder();
(, optimisticPlugin, multisig,,,,,) = builder.withMultisigMember(alice).withoutOnlyListed().build();

vm.startPrank(randomWallet);

IDAO.Action[] memory actions = new IDAO.Action[](0);
multisig.createProposal("", actions, optimisticPlugin, false);
}

modifier givenOnlyListedIsTrue() {
@@ -906,63 +918,205 @@ contract MultisigTest is AragonTest {
whenCallingCreateProposal
givenOnlyListedIsTrue
{
IDAO.Action[] memory actions = new IDAO.Action[](0);

// It reverts
vm.skip(true);

dao.grant(address(signerList), alice, UPDATE_SIGNER_LIST_PERMISSION_ID);
dao.grant(address(signerList), alice, UPDATE_SIGNER_LIST_SETTINGS_PERMISSION_ID);
signerList.updateSettings(SignerList.Settings(encryptionRegistry, 3));

vm.startPrank(randomWallet);
vm.expectRevert(abi.encodeWithSelector(Multisig.ProposalCreationForbidden.selector, randomWallet));
multisig.createProposal("", actions, optimisticPlugin, false);

// 2
vm.startPrank(taikoBridge);
vm.expectRevert(abi.encodeWithSelector(Multisig.ProposalCreationForbidden.selector, taikoBridge));
multisig.createProposal("", actions, optimisticPlugin, false);

// It reverts if listed before but not now

vm.startPrank(alice);
dao.grant(address(signerList), alice, UPDATE_SIGNER_LIST_PERMISSION_ID);

address[] memory addrs = new address[](1);
addrs[0] = alice;
signerList.removeSigners(addrs);

vm.expectRevert(abi.encodeWithSelector(Multisig.ProposalCreationForbidden.selector, alice));
multisig.createProposal("", actions, optimisticPlugin, false);
}

function test_GivenCreationCallerIsAppointedByAFormerSigner()
external
whenCallingCreateProposal
givenOnlyListedIsTrue
{
IDAO.Action[] memory actions = new IDAO.Action[](0);

// It reverts
vm.skip(true);

encryptionRegistry.appointWallet(randomWallet);
dao.grant(address(signerList), alice, UPDATE_SIGNER_LIST_PERMISSION_ID);
dao.grant(address(signerList), alice, UPDATE_SIGNER_LIST_SETTINGS_PERMISSION_ID);
signerList.updateSettings(SignerList.Settings(encryptionRegistry, 3));

address[] memory addrs = new address[](1);
addrs[0] = alice;
signerList.removeSigners(addrs);

vm.startPrank(randomWallet);
vm.expectRevert(abi.encodeWithSelector(Multisig.ProposalCreationForbidden.selector, randomWallet));
multisig.createProposal("", actions, optimisticPlugin, false);

// Undo
vm.startPrank(alice);
signerList.addSigners(addrs);

vm.startPrank(randomWallet);
multisig.createProposal("", actions, optimisticPlugin, false);
}

function test_GivenCreationCallerIsListedAndSelfAppointed()
external
whenCallingCreateProposal
givenOnlyListedIsTrue
{
IDAO.Action[] memory actions = new IDAO.Action[](0);

// It creates the proposal
vm.skip(true);

vm.startPrank(alice);
multisig.createProposal("a", actions, optimisticPlugin, false);

vm.startPrank(bob);
multisig.createProposal("b", actions, optimisticPlugin, false);

vm.startPrank(carol);
multisig.createProposal("c", actions, optimisticPlugin, false);

vm.startPrank(david);
multisig.createProposal("d", actions, optimisticPlugin, false);
}

function test_GivenCreationCallerIsListedAppointingSomeoneElseNow()
external
whenCallingCreateProposal
givenOnlyListedIsTrue
{
IDAO.Action[] memory actions = new IDAO.Action[](0);

// It creates the proposal
vm.skip(true);

vm.startPrank(alice);
encryptionRegistry.appointWallet(address(0x1234));
multisig.createProposal("a", actions, optimisticPlugin, false);

vm.startPrank(bob);
encryptionRegistry.appointWallet(address(0x2345));
multisig.createProposal("b", actions, optimisticPlugin, false);

vm.startPrank(carol);
encryptionRegistry.appointWallet(address(0x3456));
multisig.createProposal("c", actions, optimisticPlugin, false);

vm.startPrank(david);
encryptionRegistry.appointWallet(address(0x4567));
multisig.createProposal("d", actions, optimisticPlugin, false);
}

function test_GivenCreationCallerIsAppointedByACurrentSigner()
external
whenCallingCreateProposal
givenOnlyListedIsTrue
{
IDAO.Action[] memory actions = new IDAO.Action[](0);

// It creates the proposal
vm.skip(true);

vm.startPrank(alice);
encryptionRegistry.appointWallet(address(0x1234));
vm.startPrank(address(0x1234));
multisig.createProposal("a", actions, optimisticPlugin, false);

vm.startPrank(bob);
encryptionRegistry.appointWallet(address(0x2345));
vm.startPrank(address(0x2345));
multisig.createProposal("b", actions, optimisticPlugin, false);

vm.startPrank(carol);
encryptionRegistry.appointWallet(address(0x3456));
vm.startPrank(address(0x3456));
multisig.createProposal("c", actions, optimisticPlugin, false);

vm.startPrank(david);
encryptionRegistry.appointWallet(address(0x4567));
vm.startPrank(address(0x4567));
multisig.createProposal("d", actions, optimisticPlugin, false);
}

function test_GivenApproveProposalIsTrue() external whenCallingCreateProposal {
uint256 pid;
uint256 approvals;
IDAO.Action[] memory actions = new IDAO.Action[](0);

// It creates and calls approval in one go
vm.skip(true);

vm.startPrank(alice);
pid = multisig.createProposal("a", actions, optimisticPlugin, true);
(, approvals,,,,) = multisig.getProposal(pid);
assertEq(approvals, 1, "Should be 1");

vm.startPrank(bob);
pid = multisig.createProposal("b", actions, optimisticPlugin, true);
(, approvals,,,,) = multisig.getProposal(pid);
assertEq(approvals, 1, "Should be 1");
}

function test_GivenApproveProposalIsFalse() external whenCallingCreateProposal {
uint256 pid;
uint256 approvals;
IDAO.Action[] memory actions = new IDAO.Action[](0);

// It only creates the proposal
vm.skip(true);

vm.startPrank(carol);
pid = multisig.createProposal("c", actions, optimisticPlugin, false);
(, approvals,,,,) = multisig.getProposal(pid);
assertEq(approvals, 0, "Should be 0");

vm.startPrank(david);
pid = multisig.createProposal("d", actions, optimisticPlugin, false);
(, approvals,,,,) = multisig.getProposal(pid);
assertEq(approvals, 0, "Should be 0");
}

modifier givenTheProposalIsNotCreated() {
_;
}

function test_WhenCallingGetProposalBeingUncreated() external givenTheProposalIsNotCreated {
function test_WhenCallingGetProposalBeingUncreated() external view givenTheProposalIsNotCreated {
// It should return empty values
vm.skip(true);

uint256 pid;
bool executed;
uint16 approvals;
Multisig.ProposalParameters memory parameters;
bytes memory metadataURI;
IDAO.Action[] memory actions = new IDAO.Action[](0);
OptimisticTokenVotingPlugin destinationPlugin;

(executed, approvals, parameters, metadataURI, actions, destinationPlugin) = multisig.getProposal(pid);

assertEq(executed, false, "Should be false");
assertEq(approvals, 0, "Should be 0");
assertEq(parameters.minApprovals, 0, "Incorrect minApprovals");
assertEq(parameters.snapshotBlock, 0, "Incorrect snapshotBlock");
assertEq(parameters.expirationDate, 0, "Incorrect expirationDate");
assertEq(metadataURI, "", "Incorrect metadataURI");
assertEq(actions.length, 0, "Incorrect actions.length");
assertEq(address(destinationPlugin), address(0), "Incorrect destinationPlugin");
}

function test_WhenCallingCanApproveAndApproveBeingUncreated() external givenTheProposalIsNotCreated {
@@ -982,7 +1136,7 @@ contract MultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingUncreated() external givenTheProposalIsNotCreated {
function test_WhenCallingCanExecuteOrExecuteBeingUncreated() external givenTheProposalIsNotCreated {
// It canExecute should return false (when currently listed and self appointed)
// It execute should revert (when currently listed and self appointed)
// It canExecute should return false (when currently listed, appointing someone else now)
@@ -1031,7 +1185,7 @@ contract MultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingOpen() external givenTheProposalIsOpen {
function test_WhenCallingCanExecuteOrExecuteBeingOpen() external givenTheProposalIsOpen {
// It canExecute should return false (when listed on creation, self appointed now)
// It execute should revert (when listed on creation, self appointed now)
// It canExecute should return false (when listed on creation, appointing someone else now)
@@ -1065,7 +1219,7 @@ contract MultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingApproved() external givenTheProposalWasApprovedByTheAddress {
function test_WhenCallingCanExecuteOrExecuteBeingApproved() external givenTheProposalWasApprovedByTheAddress {
// It canExecute should return false (when listed on creation, self appointed now)
// It execute should revert (when listed on creation, self appointed now)
// It canExecute should return false (when currently appointed by a signer listed on creation)
@@ -1099,7 +1253,7 @@ contract MultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingPassed() external givenTheProposalPassed {
function test_WhenCallingCanExecuteOrExecuteBeingPassed() external givenTheProposalPassed {
// It canExecute should return true, always
// It execute should work, when called by anyone
// It execute should emit an event, when called by anyone
@@ -1141,7 +1295,7 @@ contract MultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingExecuted() external givenTheProposalIsAlreadyExecuted {
function test_WhenCallingCanExecuteOrExecuteBeingExecuted() external givenTheProposalIsAlreadyExecuted {
// It canExecute should return false (when listed on creation, self appointed now)
// It execute should revert (when listed on creation, self appointed now)
// It canExecute should return false (when listed on creation, appointing someone else now)
@@ -1179,7 +1333,7 @@ contract MultisigTest is AragonTest {
vm.skip(true);
}

function test_WhenCallingCanExecuteAndExecuteBeingExpired() external givenTheProposalExpired {
function test_WhenCallingCanExecuteOrExecuteBeingExpired() external givenTheProposalExpired {
// It canExecute should return false (when listed on creation, self appointed now)
// It execute should revert (when listed on creation, self appointed now)
// It canExecute should return false (when listed on creation, appointing someone else now)
26 changes: 13 additions & 13 deletions test/MultisigTree.t.yaml
Original file line number Diff line number Diff line change
@@ -95,6 +95,7 @@ MultisigTest:
- given: creation caller is not listed or appointed
then:
- it: reverts
- it: reverts if listed before but not now
- given: creation caller is appointed by a former signer
then:
- it: reverts
@@ -123,7 +124,7 @@ MultisigTest:
then:
- it: should return empty values
# Approval
- when: calling canApprove and approve [being uncreated]
- when: calling canApprove or approve [being uncreated]
then:
- it: canApprove should return false (when currently listed and self appointed)
- it: approve should revert (when currently listed and self appointed)
@@ -138,7 +139,7 @@ MultisigTest:
then:
- it: hasApproved should always return false
# Execution
- when: calling canExecute and execute [being uncreated]
- when: calling canExecute or execute [being uncreated]
then:
- it: canExecute should return false (when currently listed and self appointed)
- it: execute should revert (when currently listed and self appointed)
@@ -156,7 +157,7 @@ MultisigTest:
then:
- it: should return the right values
# Approval
- when: calling canApprove and approve [being open]
- when: calling canApprove or approve [being open]
then:
- it: canApprove should return true (when listed on creation, self appointed now)
- it: approve should work (when listed on creation, self appointed now)
@@ -183,7 +184,7 @@ MultisigTest:
then:
- it: hasApproved should return false until approved
# Execution
- when: calling canExecute and execute [being open]
- when: calling canExecute or execute [being open]
then:
- it: canExecute should return false (when listed on creation, self appointed now)
- it: execute should revert (when listed on creation, self appointed now)
@@ -201,7 +202,7 @@ MultisigTest:
then:
- it: should return the right values
# Approval
- when: calling canApprove and approve [being approved]
- when: calling canApprove or approve [being approved]
then:
- it: canApprove should return false (when listed on creation, self appointed now)
- it: approve should revert (when listed on creation, self appointed now)
@@ -216,7 +217,7 @@ MultisigTest:
then:
- it: hasApproved should return false until approved
# Execution
- when: calling canExecute and execute [being approved]
- when: calling canExecute or execute [being approved]
then:
- it: canExecute should return false (when listed on creation, self appointed now)
- it: execute should revert (when listed on creation, self appointed now)
@@ -234,7 +235,7 @@ MultisigTest:
then:
- it: should return the right values
# Approval
- when: calling canApprove and approve [being passed]
- when: calling canApprove or approve [being passed]
then:
- it: canApprove should return false (when listed on creation, self appointed now)
- it: approve should revert (when listed on creation, self appointed now)
@@ -249,7 +250,7 @@ MultisigTest:
then:
- it: hasApproved should return false until approved
# Execution
- when: calling canExecute and execute [being passed]
- when: calling canExecute or execute [being passed]
then:
- it: canExecute should return true, always
- it: execute should work, when called by anyone
@@ -270,7 +271,7 @@ MultisigTest:
then:
- it: should return the right values
# Approval
- when: calling canApprove and approve [being executed]
- when: calling canApprove or approve [being executed]
then:
- it: canApprove should return false (when listed on creation, self appointed now)
- it: approve should revert (when listed on creation, self appointed now)
@@ -285,7 +286,7 @@ MultisigTest:
then:
- it: hasApproved should return false until approved
# Execution
- when: calling canExecute and execute [being executed]
- when: calling canExecute or execute [being executed]
then:
- it: canExecute should return false (when listed on creation, self appointed now)
- it: execute should revert (when listed on creation, self appointed now)
@@ -303,7 +304,7 @@ MultisigTest:
then:
- it: should return the right values
# Approval
- when: calling canApprove and approve [being expired]
- when: calling canApprove or approve [being expired]
then:
- it: canApprove should return false (when listed on creation, self appointed now)
- it: approve should revert (when listed on creation, self appointed now)
@@ -318,7 +319,7 @@ MultisigTest:
then:
- it: hasApproved should return false until approved
# Execution
- when: calling canExecute and execute [being expired]
- when: calling canExecute or execute [being expired]
then:
- it: canExecute should return false (when listed on creation, self appointed now)
- it: execute should revert (when listed on creation, self appointed now)
@@ -328,4 +329,3 @@ MultisigTest:
- it: execute should revert (when currently appointed by a signer listed on creation)
- it: canExecute should return false (when unlisted on creation, unappointed now)
- it: execute should revert (when unlisted on creation, unappointed now)