Skip to content

Commit

Permalink
feat(space): export proposal id when executing (#245)
Browse files Browse the repository at this point in the history
* feat: export proposal id when executing

* refactor: remove proposalId from args unless needed

* refactor: remove proposal id comment

* chore: goerli and sepolia deployments

* chore: example sx interaction script

* refactor: make salt a constant in example script to reduce local vars

---------

Co-authored-by: Orlando <[email protected]>
  • Loading branch information
Orland0x and Orlando authored Dec 7, 2023
1 parent 7563118 commit a17a4ab
Show file tree
Hide file tree
Showing 16 changed files with 173 additions and 0 deletions.
21 changes: 21 additions & 0 deletions deployments/goerli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"ActiveProposalsLimiterProposalValidationStrategy": "0x399821c9Ea977387a0DEcCF1C9692B4dF925FF38",
"AvatarExecutionStrategyImplementation": "0xecE4f6b01a2d7FF5A9765cA44162D453fC455e42",
"CompTimelockCompatibleExecutionStrategyImplementation": "0x91086017D5eAEc4BeEc86ac770b5eE672e4Be589",
"CompVotingStrategy": "0x0c2De612982Efd102803161fc7C74CcA15Db932c",
"EthSigAuthenticator": "0x5f9B7D78c9a37a439D78f801E0E339C6E711e260",
"EthTxAuthenticator": "0xBA06E6cCb877C332181A6867c05c8b746A21Aed1",
"MerkleWhitelistVotingStrategy": "0x34f0AfFF5A739bBf3E285615F50e40ddAaf2A829",
"OZVotesVotingStrategy": "0x2c8631584474E750CEdF2Fb6A904f2e84777Aefe",
"OptimisticCompTimelockCompatibleExecutionStrategyImplementation": "0x77e7Aa43b28Df1e467bd4806fE3bF26F5c3EAD27",
"OptimisticTimelockExecutionStrategyImplementation": "0x49AF19f9318d55ad8e7CE743De9Ce76ED408CE0C",
"PropositionPowerAndActiveProposalsLimiterValidationStrategy": "0x358e4Ba219CC1e1c7084A14c3a504772acfc40b1",
"PropositionPowerProposalValidationStrategy": "0x6D9d6D08EF6b26348Bd18F1FC8D953696b7cf311",
"ProxyFactory": "0x4B4F7f64Be813Ccc66AEFC3bFCe2baA01188631c",
"SpaceImplementation": "0xC3031A7d3326E47D49BfF9D374d74f364B29CE4D",
"TimelockExecutionStrategyImplementation": "0xf2A1C2f2098161af98b2Cc7E382AB7F3ba86Ebc4",
"VanillaAuthenticator": "0xb9BE0a0093933968E3B4c4fC5d939B6c1Fe45142",
"VanillaProposalValidationStrategy": "0x9A39194F870c410633C170889E9025fba2113c79",
"VanillaVotingStrategy": "0xC1245C5DCa7885C73E32294140F1e5d30688c202",
"WhitelistVotingStrategy": "0x3CEE21A33751A2722413fF62dEC3dEc48e7748A4"
}
21 changes: 21 additions & 0 deletions deployments/sepolia.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"ActiveProposalsLimiterProposalValidationStrategy": "0x399821c9Ea977387a0DEcCF1C9692B4dF925FF38",
"AvatarExecutionStrategyImplementation": "0xecE4f6b01a2d7FF5A9765cA44162D453fC455e42",
"CompTimelockCompatibleExecutionStrategyImplementation": "0x91086017D5eAEc4BeEc86ac770b5eE672e4Be589",
"CompVotingStrategy": "0x0c2De612982Efd102803161fc7C74CcA15Db932c",
"EthSigAuthenticator": "0x5f9B7D78c9a37a439D78f801E0E339C6E711e260",
"EthTxAuthenticator": "0xBA06E6cCb877C332181A6867c05c8b746A21Aed1",
"MerkleWhitelistVotingStrategy": "0x34f0AfFF5A739bBf3E285615F50e40ddAaf2A829",
"OZVotesVotingStrategy": "0x2c8631584474E750CEdF2Fb6A904f2e84777Aefe",
"OptimisticCompTimelockCompatibleExecutionStrategyImplementation": "0x77e7Aa43b28Df1e467bd4806fE3bF26F5c3EAD27",
"OptimisticTimelockExecutionStrategyImplementation": "0x49AF19f9318d55ad8e7CE743De9Ce76ED408CE0C",
"PropositionPowerAndActiveProposalsLimiterValidationStrategy": "0x358e4Ba219CC1e1c7084A14c3a504772acfc40b1",
"PropositionPowerProposalValidationStrategy": "0x6D9d6D08EF6b26348Bd18F1FC8D953696b7cf311",
"ProxyFactory": "0x4B4F7f64Be813Ccc66AEFC3bFCe2baA01188631c",
"SpaceImplementation": "0xC3031A7d3326E47D49BfF9D374d74f364B29CE4D",
"TimelockExecutionStrategyImplementation": "0xf2A1C2f2098161af98b2Cc7E382AB7F3ba86Ebc4",
"VanillaAuthenticator": "0xb9BE0a0093933968E3B4c4fC5d939B6c1Fe45142",
"VanillaProposalValidationStrategy": "0x9A39194F870c410633C170889E9025fba2113c79",
"VanillaVotingStrategy": "0xC1245C5DCa7885C73E32294140F1e5d30688c202",
"WhitelistVotingStrategy": "0x3CEE21A33751A2722413fF62dEC3dEc48e7748A4"
}
118 changes: 118 additions & 0 deletions script/Example.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;

import { Script } from "forge-std/Script.sol";

import { ProxyFactory } from "../src/ProxyFactory.sol";
import { Space } from "../src/Space.sol";
import { VanillaAuthenticator } from "../src/authenticators/VanillaAuthenticator.sol";
import { TimelockExecutionStrategy } from "../src/execution-strategies/timelocks/TimelockExecutionStrategy.sol";
import { Strategy, IndexedStrategy, InitializeCalldata, Choice, MetaTransaction } from "../src/types.sol";
import { Enum } from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol";

// Example script to deploy a space, create a proposal, vote on it, and execute it.
contract Example is Script {
// Paste in the addresses from your json in the /deployments/ folder. The below are from v1.0.2 on goerli.
address public proxyFactory = address(0x4B4F7f64Be813Ccc66AEFC3bFCe2baA01188631c);
address public spaceImplementation = address(0xd9c46d5420434355d0E5Ca3e3cCb20cE7A533964);
address public vanillaVotingStrategy = address(0xC1245C5DCa7885C73E32294140F1e5d30688c202);
address public vanillaProposalValidationStrategy = address(0x9A39194F870c410633C170889E9025fba2113c79);
address public vanillaAuthenticator = address(0xb9BE0a0093933968E3B4c4fC5d939B6c1Fe45142);
address public timelockExecutionStrategyImplementation = address(0xdD5243b799759e2C64bD6CaFD7e57FcbB676f87D);

// Change the salt to deploy multiple spaces or get a 'salt already used' error
uint256 public constant saltNonce = 1234;

Check warning on line 24 in script/Example.s.sol

View workflow job for this annotation

GitHub Actions / lint

Constant name must be in capitalized SNAKE_CASE

function run() public {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);

address deployer = address(0x2842c82E20ab600F443646e1BC8550B44a513D82);

Strategy[] memory votingStrategies = new Strategy[](1);
votingStrategies[0] = Strategy(vanillaVotingStrategy, new bytes(0));

string[] memory votingStrategyMetadataURIs = new string[](1);
votingStrategyMetadataURIs[0] = "";

address[] memory authenticators = new address[](1);
authenticators[0] = vanillaAuthenticator;

string memory proposalValidationStrategyMetadataURI = "";
string memory daoURI = "";
string memory metadataURI = "";

// Deploy space
ProxyFactory(proxyFactory).deployProxy(
spaceImplementation,
abi.encodeWithSelector(
Space.initialize.selector,
InitializeCalldata(
deployer,
0,
0,
100,
Strategy(vanillaProposalValidationStrategy, new bytes(0)),
proposalValidationStrategyMetadataURI,
daoURI,
metadataURI,
votingStrategies,
votingStrategyMetadataURIs,
authenticators
)
),
saltNonce
);

address space = ProxyFactory(proxyFactory).predictProxyAddress(
spaceImplementation,
keccak256(abi.encodePacked(deployer, saltNonce))
);

// Deploy Execution Strategy with the space whitelisted
address[] memory spacesWhitelist = new address[](1);
spacesWhitelist[0] = space;
ProxyFactory(proxyFactory).deployProxy(
timelockExecutionStrategyImplementation,
abi.encodeWithSelector(
TimelockExecutionStrategy.setUp.selector,
abi.encode(deployer, deployer, spacesWhitelist, 0, 0)
),
saltNonce
);

address timelockExecutionStrategy = ProxyFactory(proxyFactory).predictProxyAddress(
timelockExecutionStrategyImplementation,
keccak256(abi.encodePacked(deployer, saltNonce))
);

// Create proposal
MetaTransaction[] memory proposalTransactions = new MetaTransaction[](1);
// Example proposal tx
proposalTransactions[0] = MetaTransaction(deployer, 0, abi.encode("hello"), Enum.Operation.Call, 0);
VanillaAuthenticator(vanillaAuthenticator).authenticate(
space,
Space.propose.selector,
abi.encode(
deployer,
"",
Strategy(timelockExecutionStrategy, abi.encode(proposalTransactions)),
new bytes(0)
)
);

// Cast vote
IndexedStrategy[] memory userVotingStrategies = new IndexedStrategy[](1);
userVotingStrategies[0] = IndexedStrategy(0, new bytes(0));
VanillaAuthenticator(vanillaAuthenticator).authenticate(
space,
Space.vote.selector,
abi.encode(deployer, 1, Choice.For, userVotingStrategies, "")
);

// Execute proposal, which queues it in the tx in timelock
Space(space).execute(1, abi.encode(proposalTransactions));

vm.stopBroadcast();
}
}
1 change: 1 addition & 0 deletions src/Space.sol
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ contract Space is ISpace, Initializable, IERC4824, UUPSUpgradeable, OwnableUpgra
proposal.finalizationStatus = FinalizationStatus.Executed;

proposal.executionStrategy.execute(
proposalId,
cachedProposal,
votePower[proposalId][Choice.For],
votePower[proposalId][Choice.Against],
Expand Down
1 change: 1 addition & 0 deletions src/execution-strategies/AvatarExecutionStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ contract AvatarExecutionStrategy is SimpleQuorumExecutionStrategy {
/// @param votesAbstain The number of abstaining votes.
/// @param payload The encoded transactions to execute.
function execute(
uint256 /* proposalId */,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ abstract contract EmergencyQuorumExecutionStrategy is IExecutionStrategy, SpaceM
}

function execute(
uint256 proposalId,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ abstract contract OptimisticQuorumExecutionStrategy is IExecutionStrategy, Space
}

function execute(
uint256 proposalId,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down
1 change: 1 addition & 0 deletions src/execution-strategies/SimpleQuorumExecutionStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ abstract contract SimpleQuorumExecutionStrategy is IExecutionStrategy, SpaceMana
}

function execute(
uint256 proposalId,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down
1 change: 1 addition & 0 deletions src/execution-strategies/VanillaExecutionStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ contract VanillaExecutionStrategy is SimpleQuorumExecutionStrategy {
}

function execute(
uint256 proposalId,

Check warning on line 24 in src/execution-strategies/VanillaExecutionStrategy.sol

View workflow job for this annotation

GitHub Actions / lint

Variable "proposalId" is unused
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ contract CompTimelockCompatibleExecutionStrategy is SimpleQuorumExecutionStrateg
/// @param votesAbstain The number of abstaining votes for the proposal.
/// @param payload The encoded payload of the proposal to execute.
function execute(
uint256 /* proposalId */,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ contract OptimisticCompTimelockCompatibleExecutionStrategy is OptimisticQuorumEx
/// @param votesAbstain The number of abstaining votes for the proposal.
/// @param payload The encoded payload of the proposal to execute.
function execute(
uint256 /* proposalId */,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ contract OptimisticTimelockExecutionStrategy is OptimisticQuorumExecutionStrateg
/// @param votesAbstain The number of abstaining votes for the proposal.
/// @param payload The proposal execution payload.
function execute(
uint256 /* proposalId */,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ contract TimelockExecutionStrategy is SimpleQuorumExecutionStrategy, IERC1155Rec
/// @param votesAbstain The number of abstaining votes for the proposal.
/// @param payload The proposal execution payload.
function execute(
uint256 /* proposalId */,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/IExecutionStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { IExecutionStrategyErrors } from "./execution-strategies/IExecutionStrat
/// @title Execution Strategy Interface
interface IExecutionStrategy is IExecutionStrategyErrors {
function execute(
uint256 proposalId,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down
1 change: 1 addition & 0 deletions test/EmergencyQuorumExecutionStrategy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ contract EmergencyQuorumExec is EmergencyQuorumExecutionStrategy {
}

function execute(
uint256 proposalId,

Check warning on line 27 in test/EmergencyQuorumExecutionStrategy.t.sol

View workflow job for this annotation

GitHub Actions / lint

Variable "proposalId" is unused
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down
1 change: 1 addition & 0 deletions test/OptimisticQuorum.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ contract OptimisticExec is OptimisticQuorumExecutionStrategy {
uint256 internal numExecuted;

function execute(
uint256 proposalId,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
Expand Down

0 comments on commit a17a4ab

Please sign in to comment.