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

refactor: add proposalId to proposalCreated event #619

Merged
merged 1 commit into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
72 changes: 36 additions & 36 deletions ethereum/src/execution-strategies/L1AvatarExecutionStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ contract L1AvatarExecutionStrategy is SimpleQuorumExecutionStrategy {
event ExecutionRelayerSet(uint256 indexed newExecutionRelayer);

/// @dev Emitted each time a proposal is executed.
event ProposalExecuted(uint256 indexed space, bytes32 executionHash);
event ProposalExecuted(uint256 indexed space, uint256 proposalId);

/// @notice Emitted when a new Avatar Execution Strategy is initialized.
/// @param _owner Address of the owner of the strategy.
Expand Down Expand Up @@ -93,69 +93,69 @@ contract L1AvatarExecutionStrategy is SimpleQuorumExecutionStrategy {

/// @notice Executes a proposal
/// @param space The address of the space that the proposal was created in.
/// @param proposalId The ID of the proposal (on Starknet).
/// @param proposal The proposal struct.
/// @param votesFor The number of votes for the proposal.
/// @param votesAgainst The number of votes against the proposal.
/// @param votesAbstain The number of votes abstaining from the proposal.
/// @param votes Struct that hold the voting power of for, against and abstain choices.
/// @param executionHash The hash of the proposal transactions.
/// @param transactions The proposal transactions to be executed.
function execute(
uint256 space,
uint256 proposalId,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
uint256 votesAbstain,
Votes memory votes,
uint256 executionHash,
MetaTransaction[] memory transactions
) external onlySpace(space) {
// Call to the Starknet core contract will fail if finalized proposal message was not received on L1.
_receiveProposal(space, proposal, votesFor, votesAgainst, votesAbstain, executionHash);
_receiveProposal(space, proposalId, proposal, votes, executionHash);

ProposalStatus proposalStatus = getProposalStatus(proposal, votesFor, votesAgainst, votesAbstain);
ProposalStatus proposalStatus =
getProposalStatus(proposal, votes.votesFor, votes.votesAgainst, votes.votesAbstain);
if ((proposalStatus != ProposalStatus.Accepted) && (proposalStatus != ProposalStatus.VotingPeriodAccepted)) {
revert InvalidProposalStatus(proposalStatus);
}

if (bytes32(executionHash) != keccak256(abi.encode(transactions))) revert InvalidPayload();

_execute(transactions);
emit ProposalExecuted(space, bytes32(executionHash));
emit ProposalExecuted(space, proposalId);
}

/// @dev Reverts if the expected message was not received from L2.
function _receiveProposal(
uint256 space,
uint256 proposalId,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
uint256 votesAbstain,
Votes memory votes,
uint256 executionHash
) internal {
// The Cairo serialization of the payload sent from L2
uint256[] memory payload = new uint256[](19);
uint256[] memory payload = new uint256[](21);
payload[0] = space;
payload[1] = uint256(proposal.startTimestamp);
payload[2] = uint256(proposal.minEndTimestamp);
payload[3] = uint256(proposal.maxEndTimestamp);
payload[4] = uint256(proposal.finalizationStatus);
payload[5] = proposal.executionPayloadHash;
payload[6] = proposal.executionStrategy;
payload[7] = proposal.authorAddressType;
payload[8] = proposal.author;
payload[9] = proposal.activeVotingStrategies & (2 ** 128 - 1);
payload[10] = proposal.activeVotingStrategies >> 128;

payload[11] = votesFor & (2 ** 128 - 1);
payload[12] = votesFor >> 128;

payload[13] = votesAgainst & (2 ** 128 - 1);
payload[14] = votesAgainst >> 128;

payload[15] = votesAbstain & (2 ** 128 - 1);
payload[16] = votesAbstain >> 128;

payload[17] = executionHash & (2 ** 128 - 1);
payload[18] = executionHash >> 128;
payload[1] = proposalId & (2 ** 128 - 1);
payload[2] = proposalId >> 128;
payload[3] = uint256(proposal.startTimestamp);
payload[4] = uint256(proposal.minEndTimestamp);
payload[5] = uint256(proposal.maxEndTimestamp);
payload[6] = uint256(proposal.finalizationStatus);
payload[7] = proposal.executionPayloadHash;
payload[8] = proposal.executionStrategy;
payload[9] = proposal.authorAddressType;
payload[10] = proposal.author;
payload[11] = proposal.activeVotingStrategies & (2 ** 128 - 1);
payload[12] = proposal.activeVotingStrategies >> 128;

payload[13] = votes.votesFor & (2 ** 128 - 1);
payload[14] = votes.votesFor >> 128;

payload[15] = votes.votesAgainst & (2 ** 128 - 1);
payload[16] = votes.votesAgainst >> 128;

payload[17] = votes.votesAbstain & (2 ** 128 - 1);
payload[18] = votes.votesAbstain >> 128;

payload[19] = executionHash & (2 ** 128 - 1);
payload[20] = executionHash >> 128;

// If proposal execution message did not exist/not received yet, then this will revert.
IStarknetCore(starknetCore).consumeMessageFromL2(executionRelayer, payload);
Expand Down
102 changes: 41 additions & 61 deletions ethereum/src/mocks/L1AvatarExecutionStrategyMockMessaging.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ contract L1AvatarExecutionStrategyMockMessaging is SimpleQuorumExecutionStrategy
event ExecutionRelayerSet(uint256 indexed newExecutionRelayer);

/// @dev Emitted each time a proposal is executed.
event ProposalExecuted(uint256 indexed space, bytes32 executionHash);
event ProposalExecuted(uint256 indexed space, uint256 proposalId);

/// @notice Emitted when a new Avatar Execution Strategy is initialized.
/// @param _owner Address of the owner of the strategy.
Expand All @@ -48,37 +48,17 @@ contract L1AvatarExecutionStrategyMockMessaging is SimpleQuorumExecutionStrategy
uint256 _quorum
);

/// @notice Constructor
/// @param _owner Address of the owner of this contract.
/// @param _target Address of the avatar that this module will pass transactions to.
/// @param _starknetCore Address of the StarkNet Core contract.
/// @param _executionRelayer Address of the StarkNet contract that will send execution details to this contract in a L2 -> L1 message
/// @param _starknetSpaces Array of whitelisted space contracts.
/// @param _quorum The quorum required to execute a proposal.
constructor(
constructor() {}

/// @notice Initialization function, should be called immediately after deploying a new proxy to this contract.
function setUp(
address _owner,
address _target,
address _starknetCore,
uint256 _executionRelayer,
uint256[] memory _starknetSpaces,
uint256 _quorum
) {
bytes memory initParams =
abi.encode(_owner, _target, _starknetCore, _executionRelayer, _starknetSpaces, _quorum);
setUp(initParams);
}

/// @notice Initialization function, should be called immediately after deploying a new proxy to this contract.
/// @param initParams ABI encoded parameters, in the same order as the constructor.
function setUp(bytes memory initParams) public initializer {
(
address _owner,
address _target,
address _starknetCore,
uint256 _executionRelayer,
uint256[] memory _starknetSpaces,
uint256 _quorum
) = abi.decode(initParams, (address, address, address, uint256, uint256[], uint256));
) public initializer {
__Ownable_init();
transferOwnership(_owner);
__SpaceManager_init(_starknetSpaces);
Expand Down Expand Up @@ -112,69 +92,69 @@ contract L1AvatarExecutionStrategyMockMessaging is SimpleQuorumExecutionStrategy

/// @notice Executes a proposal
/// @param space The address of the space that the proposal was created in.
/// @param proposalId The ID of the proposal (on Starknet).
/// @param proposal The proposal struct.
/// @param votesFor The number of votes for the proposal.
/// @param votesAgainst The number of votes against the proposal.
/// @param votesAbstain The number of votes abstaining from the proposal.
/// @param votes Struct that hold the voting power of for, against and abstain choices.
/// @param executionHash The hash of the proposal transactions.
/// @param transactions The proposal transactions to be executed.
function execute(
uint256 space,
uint256 proposalId,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
uint256 votesAbstain,
Votes memory votes,
uint256 executionHash,
MetaTransaction[] memory transactions
) external onlySpace(space) {
// Call to the Starknet core contract will fail if finalized proposal message was not received on L1.
_receiveProposal(space, proposal, votesFor, votesAgainst, votesAbstain, executionHash);
_receiveProposal(space, proposalId, proposal, votes, executionHash);

ProposalStatus proposalStatus = getProposalStatus(proposal, votesFor, votesAgainst, votesAbstain);
ProposalStatus proposalStatus =
getProposalStatus(proposal, votes.votesFor, votes.votesAgainst, votes.votesAbstain);
if ((proposalStatus != ProposalStatus.Accepted) && (proposalStatus != ProposalStatus.VotingPeriodAccepted)) {
revert InvalidProposalStatus(proposalStatus);
}

if (bytes32(executionHash) != keccak256(abi.encode(transactions))) revert InvalidPayload();

_execute(transactions);
emit ProposalExecuted(space, bytes32(executionHash));
emit ProposalExecuted(space, proposalId);
}

/// @dev Reverts if the expected message was not received from L2.
function _receiveProposal(
uint256 space,
uint256 proposalId,
Proposal memory proposal,
uint256 votesFor,
uint256 votesAgainst,
uint256 votesAbstain,
Votes memory votes,
uint256 executionHash
) internal {
// The Cairo serialization of the payload sent from L2
uint256[] memory payload = new uint256[](19);
uint256[] memory payload = new uint256[](21);
payload[0] = space;
payload[1] = uint256(proposal.startTimestamp);
payload[2] = uint256(proposal.minEndTimestamp);
payload[3] = uint256(proposal.maxEndTimestamp);
payload[4] = uint256(proposal.finalizationStatus);
payload[5] = proposal.executionPayloadHash;
payload[6] = proposal.executionStrategy;
payload[7] = proposal.authorAddressType;
payload[8] = proposal.author;
payload[9] = proposal.activeVotingStrategies & (2 ** 128 - 1);
payload[10] = proposal.activeVotingStrategies >> 128;

payload[11] = votesFor & (2 ** 128 - 1);
payload[12] = votesFor >> 128;

payload[13] = votesAgainst & (2 ** 128 - 1);
payload[14] = votesAgainst >> 128;

payload[15] = votesAbstain & (2 ** 128 - 1);
payload[16] = votesAbstain >> 128;

payload[17] = executionHash & (2 ** 128 - 1);
payload[18] = executionHash >> 128;
payload[1] = proposalId & (2 ** 128 - 1);
payload[2] = proposalId >> 128;
payload[3] = uint256(proposal.startTimestamp);
payload[4] = uint256(proposal.minEndTimestamp);
payload[5] = uint256(proposal.maxEndTimestamp);
payload[6] = uint256(proposal.finalizationStatus);
payload[7] = proposal.executionPayloadHash;
payload[8] = proposal.executionStrategy;
payload[9] = proposal.authorAddressType;
payload[10] = proposal.author;
payload[11] = proposal.activeVotingStrategies & (2 ** 128 - 1);
payload[12] = proposal.activeVotingStrategies >> 128;

payload[13] = votes.votesFor & (2 ** 128 - 1);
payload[14] = votes.votesFor >> 128;

payload[15] = votes.votesAgainst & (2 ** 128 - 1);
payload[16] = votes.votesAgainst >> 128;

payload[17] = votes.votesAbstain & (2 ** 128 - 1);
payload[18] = votes.votesAbstain >> 128;

payload[19] = executionHash & (2 ** 128 - 1);
payload[20] = executionHash >> 128;

// If proposal execution message did not exist/not received yet, then this will revert.
MockStarknetMessaging(starknetCore).consumeMessageFromL2(executionRelayer, payload);
Expand Down
9 changes: 7 additions & 2 deletions ethereum/src/types.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ struct MetaTransaction {
uint256 value;
bytes data;
Enum.Operation operation;
// We use a salt so that the struct can always be unique and we can use its hash as a unique identifier.
uint256 salt;
}

/// @notice The set of possible finalization statuses for a proposal.
Expand All @@ -40,6 +38,13 @@ struct Proposal {
uint256 activeVotingStrategies;
}

/// @notice Struct to store the votes for a proposal. Used because of Solidity's stack limitations.
struct Votes {
uint256 votesFor;
uint256 votesAgainst;
uint256 votesAbstain;
}

/// @notice The set of possible statuses for a proposal.
enum ProposalStatus {
VotingDelay,
Expand Down
1 change: 1 addition & 0 deletions starknet/src/execution_strategies/eth_relayer.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ mod EthRelayerExecutionStrategy {
// Serialize the payload to be sent to the L1 execution strategy
let mut l1_payload = array![];
space.serialize(ref l1_payload);
proposal_id.serialize(ref l1_payload);
proposal.serialize(ref l1_payload);
votes_for.serialize(ref l1_payload);
votes_against.serialize(ref l1_payload);
Expand Down
Loading
Loading