Skip to content

Commit

Permalink
Merge pull request #20 from aragon/f/proposal-id-mapping
Browse files Browse the repository at this point in the history
Proposal id mapping (optimistic)
  • Loading branch information
carlosgj94 authored Jul 15, 2024
2 parents 54bb2f8 + c3982f3 commit 1d6af3f
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 18 deletions.
29 changes: 29 additions & 0 deletions DEPLOYMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Deployment list

## Mainnet

## Sepolia

On June 6th 2024:

```
Chain ID: 11155111
Deploying from: 0x424797Ed6d902E17b9180BFcEF452658e148e0Ab
Test voting token: 0xf7A8F99a1d0AFB3C95f80770223b00e062C6Ec19
Factory contract: 0x8c99CDb5567206660CA9b77C3B26C13F6C674952
DAO contract: 0x6C477915CC803518723d4Bdd5B2170cf38A57203
- Multisig plugin: 0x0fC611670228A61824c317926f30e8a2615aa1A3
- Emergency multisig plugin: 0x619d6661eA06b917e26694f23c5Bb32fa0456773
- Optimistic token voting plugin: 0xC9304930f6a4fB2DAe74A17032426Aa1E817897A
- Multisig plugin repository: 0x841E3dA30697C8FC7224a43952041001545a2443
- Emergency multisig plugin repository: 0x6E8578B1519a04BA9262CB633B06624f636D4795
- Optimistic token voting plugin repository: 0x58CA6f90edB98f9213353f456c685ABF253edAA7
Public key registry 0xadAb459A189AAaa17D4807805e6Fab55d3fb5C44
Delegation wall 0x0cE7f031BA69abFB404fE148dD09F597db8AB3a0
```

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The Security Council has a standard multisig plugin and an emergency variant. Th

[Learn more about Aragon OSx](#protocol-overview).

See [Deploying the DAO](#deploying-the-dao) below.
See [Deploying the DAO](#deploying-the-dao) below and check out the [latest deployments](./DEPLOYMENTS.md).

## Optimistic Token Voting plugin

Expand Down
4 changes: 2 additions & 2 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ contract Deploy is Script {
);

console.log("Chain ID:", block.chainid);
console.log("Deploying from:", vm.addr(vm.envUint("DEPLOYMENT_PRIVATE_KEY")));
console.log("");
console.log("Deploying from:", vm.addr(vm.envUint("DEPLOYMENT_PRIVATE_KEY")));

TaikoDaoFactory.DeploymentSettings memory settings;
if (block.chainid == 1) {
Expand All @@ -55,6 +55,7 @@ contract Deploy is Script {

// Print summary
console.log("Factory contract:", address(factory));
console.log("");
console.log("DAO contract:", address(daoDeployment.dao));
console.log("");

Expand Down Expand Up @@ -110,7 +111,6 @@ contract Deploy is Script {
address votingToken = createTestToken(multisigMembers, taikoBridgeAddress);

console.log("Test voting token:", votingToken);
console.log("");

settings = TaikoDaoFactory.DeploymentSettings({
// Taiko contract settings
Expand Down
8 changes: 8 additions & 0 deletions src/DelegationWall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ contract DelegationWall {

/// @dev Stores the data registered by the delegate candidates
mapping(address => Candidate) public candidates;

/// @dev Keeps track of the addresses that have been already registered, used to enumerate.
address[] public candidateAddresses;

Expand All @@ -33,6 +34,13 @@ contract DelegationWall {
emit CandidateRegistered(msg.sender, _contentUrl);
}

/// @notice Returns the list of candidate addresses registered
/// @dev Use this function to get all addresses in a single call. You can still call candidateAddresses[idx] to resolve them one by one.
function getCandidateAddresses() public view returns (address[] memory) {
return candidateAddresses;
}

/// @notice Returns the number of candidate entries available
function candidateCount() public view returns (uint256) {
return candidateAddresses.length;
}
Expand Down
7 changes: 6 additions & 1 deletion src/OptimisticTokenVotingPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ contract OptimisticTokenVotingPlugin is
/// @notice A mapping between proposal IDs and proposal information.
mapping(uint256 => Proposal) internal proposals;

/// @notice A mapping to enumerate proposal ID's by index
mapping(uint256 => uint256) public proposalIds;

/// @notice Emitted when the vetoing settings are updated.
/// @param minVetoRatio The minimum veto ratio needed to defeat the proposal, as a fraction of 1_000_000.
/// @param minDuration The minimum duration of the proposal vote in seconds.
Expand Down Expand Up @@ -358,6 +361,8 @@ contract OptimisticTokenVotingPlugin is
_actions: _actions,
_allowFailureMap: _allowFailureMap
});
// Index the ID to make it enumerable. Proposal ID's contain timestamps and cannot be iterated
proposalIds[proposalCount() - 1] = proposalId;

// Store proposal related information
Proposal storage proposal_ = proposals[proposalId];
Expand Down Expand Up @@ -549,5 +554,5 @@ contract OptimisticTokenVotingPlugin is
}

/// @notice This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain (see [OpenZeppelin's guide about storage gaps](https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps)).
uint256[45] private __gap;
uint256[44] private __gap;
}
17 changes: 14 additions & 3 deletions src/PublicKeyRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ pragma solidity ^0.8.17;
/// @author Aragon Association - 2024
/// @notice A smart contract where any wallet can register its own libsodium public key for encryption purposes
contract PublicKeyRegistry {
mapping(address => bytes32) internal publicKeys;
mapping(address => bytes32) public publicKeys;

/// @dev Allows to enumerate the wallets that have a public key registered
address[] public registeredWallets;

/// @notice Emitted when a public key is registered
event PublicKeyRegistered(address wallet, bytes32 publicKey);
Expand All @@ -19,9 +22,17 @@ contract PublicKeyRegistry {

publicKeys[msg.sender] = _publicKey;
emit PublicKeyRegistered(msg.sender, _publicKey);
registeredWallets.push(msg.sender);
}

/// @notice Returns the list of wallets that have registered a public key
/// @dev Use this function to get all addresses in a single call. You can still call registeredWallets[idx] to resolve them one by one.
function getRegisteredWallets() public view returns (address[] memory) {
return registeredWallets;
}

function getPublicKey(address _wallet) public view returns (bytes32) {
return publicKeys[_wallet];
/// @notice Returns the number of publicKey entries available
function registeredWalletCount() public view returns (uint256) {
return registeredWallets.length;
}
}
18 changes: 18 additions & 0 deletions test/DelegationWall.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,24 @@ contract EmergencyMultisigTest is AragonTest {
assertEq(wall.candidateAddresses(3), david, "Incorrect candidate address");
}

function test_ShouldLoadTheRegisteredAddresses() public {
vm.startPrank(alice);
wall.register("https://");
vm.startPrank(bob);
wall.register("https://taiko.xyz");
vm.startPrank(carol);
wall.register("https://x.com/carol");
vm.startPrank(david);
wall.register("https://defeat-goliath.org");

address[] memory candidates = wall.getCandidateAddresses();
assertEq(candidates.length, 4);
assertEq(candidates[0], alice);
assertEq(candidates[1], bob);
assertEq(candidates[2], carol);
assertEq(candidates[3], david);
}

function test_ShouldEmitAnEventWhenRegistering() public {
// Alice
vm.startPrank(alice);
Expand Down
39 changes: 39 additions & 0 deletions test/OptimisticTokenVotingPlugin.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,45 @@ contract OptimisticTokenVotingPluginTest is AragonTest {
assertEq(proposalId, expectedPid, "Should have created proposal 2");
}

function test_CreateProposalIncrementsTheProposalCounter() public {
IDAO.Action[] memory actions = new IDAO.Action[](0);
assertEq(optimisticPlugin.proposalCount(), 0);
optimisticPlugin.createProposal("", actions, 0, 10 days);
assertEq(optimisticPlugin.proposalCount(), 1);
optimisticPlugin.createProposal("ipfs://", actions, 0, 10 days);
assertEq(optimisticPlugin.proposalCount(), 2);
optimisticPlugin.createProposal("", actions, 255, 15 days);
assertEq(optimisticPlugin.proposalCount(), 3);
optimisticPlugin.createProposal("", actions, 127, 20 days);
assertEq(optimisticPlugin.proposalCount(), 4);
optimisticPlugin.createProposal("ipfs://meta", actions, 0, 10 days);
assertEq(optimisticPlugin.proposalCount(), 5);
optimisticPlugin.createProposal("", actions, 0, 100 days);
assertEq(optimisticPlugin.proposalCount(), 6);
}

function test_CreateProposalIndexesThePid() public {
uint256 expectedPid = uint256(block.timestamp) << 128 | uint256(block.timestamp + 10 days) << 64;

IDAO.Action[] memory actions = new IDAO.Action[](0);
// 1
assertEq(optimisticPlugin.proposalIds(0), 0);
optimisticPlugin.createProposal("", actions, 0, 10 days);
assertEq(optimisticPlugin.proposalIds(0), expectedPid);

// 2
expectedPid = uint256(block.timestamp) << 128 | uint256(block.timestamp + 100 days) << 64 | 1;
assertEq(optimisticPlugin.proposalIds(1), 0);
optimisticPlugin.createProposal("ipfs://meta", actions, 0, 100 days);
assertEq(optimisticPlugin.proposalIds(1), expectedPid);

// 3
expectedPid = uint256(block.timestamp) << 128 | uint256(block.timestamp + 50 days) << 64 | 2;
assertEq(optimisticPlugin.proposalIds(2), 0);
optimisticPlugin.createProposal("", actions, 0, 50 days);
assertEq(optimisticPlugin.proposalIds(2), expectedPid);
}

function test_CreateProposalEmitsAnEvent() public {
uint256 expectedPid = uint256(block.timestamp) << 128 | uint256(block.timestamp + 10 days) << 64;

Expand Down
83 changes: 72 additions & 11 deletions test/PublicKeyRegistry.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,37 @@ contract EmergencyMultisigTest is AragonTest {
}

function test_ShouldRegisterAPublicKey() public {
assertEq(registry.getPublicKey(alice), 0x0000000000000000000000000000000000000000000000000000000000000000);
assertEq(registry.publicKeys(alice), 0x0000000000000000000000000000000000000000000000000000000000000000);

// Alice
vm.startPrank(alice);
registry.setPublicKey(0x1234000000000000000000000000000000000000000000000000000000000000);

assertEq(registry.getPublicKey(alice), 0x1234000000000000000000000000000000000000000000000000000000000000);
assertEq(registry.publicKeys(alice), 0x1234000000000000000000000000000000000000000000000000000000000000);

// Bob
vm.startPrank(bob);
registry.setPublicKey(0x0000567800000000000000000000000000000000000000000000000000000000);

assertEq(registry.getPublicKey(alice), 0x1234000000000000000000000000000000000000000000000000000000000000);
assertEq(registry.getPublicKey(bob), 0x0000567800000000000000000000000000000000000000000000000000000000);
assertEq(registry.publicKeys(alice), 0x1234000000000000000000000000000000000000000000000000000000000000);
assertEq(registry.publicKeys(bob), 0x0000567800000000000000000000000000000000000000000000000000000000);

// Carol
vm.startPrank(carol);
registry.setPublicKey(0x0000000090ab0000000000000000000000000000000000000000000000000000);

assertEq(registry.getPublicKey(alice), 0x1234000000000000000000000000000000000000000000000000000000000000);
assertEq(registry.getPublicKey(bob), 0x0000567800000000000000000000000000000000000000000000000000000000);
assertEq(registry.getPublicKey(carol), 0x0000000090ab0000000000000000000000000000000000000000000000000000);
assertEq(registry.publicKeys(alice), 0x1234000000000000000000000000000000000000000000000000000000000000);
assertEq(registry.publicKeys(bob), 0x0000567800000000000000000000000000000000000000000000000000000000);
assertEq(registry.publicKeys(carol), 0x0000000090ab0000000000000000000000000000000000000000000000000000);

// David
vm.startPrank(david);
registry.setPublicKey(0x000000000000cdef000000000000000000000000000000000000000000000000);

assertEq(registry.getPublicKey(alice), 0x1234000000000000000000000000000000000000000000000000000000000000);
assertEq(registry.getPublicKey(bob), 0x0000567800000000000000000000000000000000000000000000000000000000);
assertEq(registry.getPublicKey(carol), 0x0000000090ab0000000000000000000000000000000000000000000000000000);
assertEq(registry.getPublicKey(david), 0x000000000000cdef000000000000000000000000000000000000000000000000);
assertEq(registry.publicKeys(alice), 0x1234000000000000000000000000000000000000000000000000000000000000);
assertEq(registry.publicKeys(bob), 0x0000567800000000000000000000000000000000000000000000000000000000);
assertEq(registry.publicKeys(carol), 0x0000000090ab0000000000000000000000000000000000000000000000000000);
assertEq(registry.publicKeys(david), 0x000000000000cdef000000000000000000000000000000000000000000000000);
}

function test_ShouldEmitARegistrationEvent() public {
Expand Down Expand Up @@ -102,4 +102,65 @@ contract EmergencyMultisigTest is AragonTest {
vm.expectRevert(abi.encodeWithSelector(AlreadySet.selector));
registry.setPublicKey(0x000000000000cdef000000000000000000000000000000000000000000000000);
}

function test_ShouldCountRegisteredCandidates() public {
assertEq(registry.registeredWalletCount(), 0, "Incorrect count");

// Alice
vm.startPrank(alice);
registry.setPublicKey(bytes32(uint256(1234)));
assertEq(registry.registeredWalletCount(), 1, "Incorrect count");

// Bob
vm.startPrank(bob);
registry.setPublicKey(bytes32(uint256(2345)));
assertEq(registry.registeredWalletCount(), 2, "Incorrect count");

// Carol
vm.startPrank(carol);
registry.setPublicKey(bytes32(uint256(3456)));
assertEq(registry.registeredWalletCount(), 3, "Incorrect count");

// David
vm.startPrank(david);
registry.setPublicKey(bytes32(uint256(4567)));
assertEq(registry.registeredWalletCount(), 4, "Incorrect count");
}

function test_ShouldEnumerateRegisteredCandidates() public {
// Register
vm.startPrank(alice);
registry.setPublicKey(bytes32(uint256(1234)));
vm.startPrank(bob);
registry.setPublicKey(bytes32(uint256(2345)));
vm.startPrank(carol);
registry.setPublicKey(bytes32(uint256(3456)));
vm.startPrank(david);
registry.setPublicKey(bytes32(uint256(4567)));

assertEq(registry.registeredWalletCount(), 4, "Incorrect count");

assertEq(registry.registeredWallets(0), alice);
assertEq(registry.registeredWallets(1), bob);
assertEq(registry.registeredWallets(2), carol);
assertEq(registry.registeredWallets(3), david);
}

function test_ShouldLoadTheRegisteredAddresses() public {
vm.startPrank(alice);
registry.setPublicKey(bytes32(uint256(1234)));
vm.startPrank(bob);
registry.setPublicKey(bytes32(uint256(2345)));
vm.startPrank(carol);
registry.setPublicKey(bytes32(uint256(3456)));
vm.startPrank(david);
registry.setPublicKey(bytes32(uint256(4567)));

address[] memory candidates = registry.getRegisteredWallets();
assertEq(candidates.length, 4);
assertEq(candidates[0], alice);
assertEq(candidates[1], bob);
assertEq(candidates[2], carol);
assertEq(candidates[3], david);
}
}

0 comments on commit 1d6af3f

Please sign in to comment.