diff --git a/ethereum/src/execution-strategies/L1AvatarExecutionStrategy.sol b/ethereum/src/execution-strategies/L1AvatarExecutionStrategy.sol index 01bd5f79..b821a5ef 100644 --- a/ethereum/src/execution-strategies/L1AvatarExecutionStrategy.sol +++ b/ethereum/src/execution-strategies/L1AvatarExecutionStrategy.sol @@ -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. @@ -93,25 +93,24 @@ 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); } @@ -119,43 +118,44 @@ contract L1AvatarExecutionStrategy is SimpleQuorumExecutionStrategy { 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); diff --git a/ethereum/src/mocks/L1AvatarExecutionStrategyMockMessaging.sol b/ethereum/src/mocks/L1AvatarExecutionStrategyMockMessaging.sol index d2608988..b98b65e5 100644 --- a/ethereum/src/mocks/L1AvatarExecutionStrategyMockMessaging.sol +++ b/ethereum/src/mocks/L1AvatarExecutionStrategyMockMessaging.sol @@ -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. @@ -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); @@ -112,25 +92,24 @@ 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); } @@ -138,43 +117,44 @@ contract L1AvatarExecutionStrategyMockMessaging is SimpleQuorumExecutionStrategy 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); diff --git a/ethereum/src/types.sol b/ethereum/src/types.sol index ac829d5e..8c258d34 100644 --- a/ethereum/src/types.sol +++ b/ethereum/src/types.sol @@ -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. @@ -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, diff --git a/starknet/src/execution_strategies/eth_relayer.cairo b/starknet/src/execution_strategies/eth_relayer.cairo index a9edeeef..c31c8a48 100644 --- a/starknet/src/execution_strategies/eth_relayer.cairo +++ b/starknet/src/execution_strategies/eth_relayer.cairo @@ -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); diff --git a/tests/l1-avatar-execution.test.ts b/tests/l1-avatar-execution.test.ts index 5b221cd7..64e7f5b8 100644 --- a/tests/l1-avatar-execution.test.ts +++ b/tests/l1-avatar-execution.test.ts @@ -113,13 +113,12 @@ describe('L1 Avatar Execution', function () { value: 0, data: '0x11', operation: 0, - salt: 1, }; const abiCoder = new ethers.utils.AbiCoder(); const executionHash = ethers.utils.keccak256( abiCoder.encode( - ['tuple(address to, uint256 value, bytes data, uint8 operation, uint256 salt)[]'], + ['tuple(address to, uint256 value, bytes data, uint8 operation)[]'], [[proposalTx]], ), ); @@ -184,17 +183,16 @@ describe('L1 Avatar Execution', function () { const message_payload = flushL2Response.consumed_messages.from_l2[0].payload; // Proposal data can either be extracted from the message sent to L1 (as done here) or pulled from the contract directly - const [proposal, forVotes, againstVotes, abstainVotes] = extractMessagePayload(message_payload); + const [proposalId, proposal, votes] = extractMessagePayload(message_payload); await expect(l1AvatarExecutionStrategy.execute( space.address, + proposalId, proposal, - forVotes, - againstVotes, - abstainVotes, + votes, executionHash, [proposalTx], - )).to.emit(l1AvatarExecutionStrategy, 'ProposalExecuted').withArgs(space.address.toString(), executionHash); + )).to.emit(l1AvatarExecutionStrategy, 'ProposalExecuted').withArgs(space.address.toString(), proposalId); }, 10000000); it('should execute a proposal with multiple txs via the Avatar Execution Strategy connected to a Safe', async function () { @@ -208,7 +206,6 @@ describe('L1 Avatar Execution', function () { value: 0, data: '0x11', operation: 0, - salt: 1, }; const proposalTx2 = { @@ -222,7 +219,7 @@ describe('L1 Avatar Execution', function () { const abiCoder = new ethers.utils.AbiCoder(); const executionHash = ethers.utils.keccak256( abiCoder.encode( - ['tuple(address to, uint256 value, bytes data, uint8 operation, uint256 salt)[]'], + ['tuple(address to, uint256 value, bytes data, uint8 operation)[]'], [[proposalTx, proposalTx2]], ), ); @@ -287,14 +284,13 @@ describe('L1 Avatar Execution', function () { const message_payload = flushL2Response.consumed_messages.from_l2[0].payload; // Proposal data can either be extracted from the message sent to L1 (as done here) or pulled from the contract directly - const [proposal, forVotes, againstVotes, abstainVotes] = extractMessagePayload(message_payload); + const [proposalId, proposal, votes] = extractMessagePayload(message_payload); await l1AvatarExecutionStrategy.execute( space.address, + proposalId, proposal, - forVotes, - againstVotes, - abstainVotes, + votes, executionHash, [proposalTx, proposalTx2], ); @@ -314,13 +310,12 @@ describe('L1 Avatar Execution', function () { value: 0, data: '0x11', operation: 0, - salt: 1, }; const abiCoder = new ethers.utils.AbiCoder(); const executionHash = ethers.utils.keccak256( abiCoder.encode( - ['tuple(address to, uint256 value, bytes data, uint8 operation, uint256 salt)[]'], + ['tuple(address to, uint256 value, bytes data, uint8 operation)[]'], [[proposalTx]], ), ); @@ -385,15 +380,14 @@ describe('L1 Avatar Execution', function () { const message_payload = flushL2Response.consumed_messages.from_l2[0].payload; // Proposal data can either be extracted from the message sent to L1 (as done here) or pulled from the contract directly - const [proposal, forVotes, againstVotes, abstainVotes] = extractMessagePayload(message_payload); + const [proposalId, proposal, votes] = extractMessagePayload(message_payload); await expect( l1AvatarExecutionStrategy.execute( space.address, + proposalId, proposal, - forVotes, - againstVotes, - abstainVotes, + votes, executionHash, [proposalTx], ), @@ -414,13 +408,12 @@ describe('L1 Avatar Execution', function () { value: 0, data: '0x22', operation: 0, - salt: 1, }; const abiCoder = new ethers.utils.AbiCoder(); const executionHash = ethers.utils.keccak256( abiCoder.encode( - ['tuple(address to, uint256 value, bytes data, uint8 operation, uint256 salt)[]'], + ['tuple(address to, uint256 value, bytes data, uint8 operation)[]'], [[proposalTx]], ), ); @@ -484,16 +477,17 @@ describe('L1 Avatar Execution', function () { const flushL2Response = await starknet.devnet.flush(); const message_payload = flushL2Response.consumed_messages.from_l2[0].payload; // Proposal data can either be extracted from the message sent to L1 (as done here) or pulled from the contract directly - const [proposal, forVotes, againstVotes, abstainVotes] = extractMessagePayload(message_payload); + const [proposalId, proposal, votes] = extractMessagePayload(message_payload); + + // Manually set an incorrect votesFor value + votes.votesFor = 10; - // Incorrect forVotes value was supplied await expect( l1AvatarExecutionStrategy.execute( space.address, + proposalId, proposal, - 10, - againstVotes, - abstainVotes, + votes, executionHash, [proposalTx], ), @@ -511,13 +505,12 @@ describe('L1 Avatar Execution', function () { value: 0, data: '0x22', operation: 0, - salt: 1, }; const abiCoder = new ethers.utils.AbiCoder(); const executionHash = ethers.utils.keccak256( abiCoder.encode( - ['tuple(address to, uint256 value, bytes data, uint8 operation, uint256 salt)[]'], + ['tuple(address to, uint256 value, bytes data, uint8 operation)[]'], [[proposalTx]], ), ); @@ -581,7 +574,7 @@ describe('L1 Avatar Execution', function () { const flushL2Response = await starknet.devnet.flush(); const message_payload = flushL2Response.consumed_messages.from_l2[0].payload; // Proposal data can either be extracted from the message sent to L1 (as done here) or pulled from the contract directly - const [proposal, forVotes, againstVotes, abstainVotes] = extractMessagePayload(message_payload); + const [proposalId, proposal, votes] = extractMessagePayload(message_payload); const fakeProposalTx = { to: signer.address, @@ -595,10 +588,9 @@ describe('L1 Avatar Execution', function () { await expect( l1AvatarExecutionStrategy.execute( space.address, + proposalId, proposal, - forVotes, - againstVotes, - abstainVotes, + votes, executionHash, [fakeProposalTx], ), @@ -616,13 +608,12 @@ describe('L1 Avatar Execution', function () { value: 0, data: '0x22', operation: 0, - salt: 1, }; const abiCoder = new ethers.utils.AbiCoder(); const executionHash = ethers.utils.keccak256( abiCoder.encode( - ['tuple(address to, uint256 value, bytes data, uint8 operation, uint256 salt)[]'], + ['tuple(address to, uint256 value, bytes data, uint8 operation)[]'], [[proposalTx]], ), ); @@ -686,16 +677,15 @@ describe('L1 Avatar Execution', function () { const flushL2Response = await starknet.devnet.flush(); const message_payload = flushL2Response.consumed_messages.from_l2[0].payload; // Proposal data can either be extracted from the message sent to L1 (as done here) or pulled from the contract directly - const [proposal, forVotes, againstVotes, abstainVotes] = extractMessagePayload(message_payload); + const [proposalId, proposal, votes] = extractMessagePayload(message_payload); // For some reason CI fails with revertedWith('InvalidProposalStatus') but works locally. await expect( l1AvatarExecutionStrategy.execute( space.address, + proposalId, proposal, - forVotes, - againstVotes, - abstainVotes, + votes, executionHash, [proposalTx], ), @@ -713,13 +703,12 @@ describe('L1 Avatar Execution', function () { value: 0, data: '0x22', operation: 0, - salt: 1, }; const abiCoder = new ethers.utils.AbiCoder(); const executionHash = ethers.utils.keccak256( abiCoder.encode( - ['tuple(address to, uint256 value, bytes data, uint8 operation, uint256 salt)[]'], + ['tuple(address to, uint256 value, bytes data, uint8 operation)[]'], [[proposalTx]], ), ); @@ -783,16 +772,15 @@ describe('L1 Avatar Execution', function () { const flushL2Response = await starknet.devnet.flush(); const message_payload = flushL2Response.consumed_messages.from_l2[0].payload; // Proposal data can either be extracted from the message sent to L1 (as done here) or pulled from the contract directly - const [proposal, forVotes, againstVotes, abstainVotes] = extractMessagePayload(message_payload); + const [proposalId, proposal, votes] = extractMessagePayload(message_payload); // For some reason CI fails with revertedWith('InvalidProposalStatus') but works locally. await expect( l1AvatarExecutionStrategy.execute( space.address, + proposalId, proposal, - forVotes, - againstVotes, - abstainVotes, + votes, executionHash, [proposalTx], ), @@ -810,13 +798,12 @@ describe('L1 Avatar Execution', function () { value: 0, data: '0x22', operation: 0, - salt: 1, }; const abiCoder = new ethers.utils.AbiCoder(); const executionHash = ethers.utils.keccak256( abiCoder.encode( - ['tuple(address to, uint256 value, bytes data, uint8 operation, uint256 salt)[]'], + ['tuple(address to, uint256 value, bytes data, uint8 operation)[]'], [[proposalTx]], ), ); @@ -867,16 +854,15 @@ describe('L1 Avatar Execution', function () { const flushL2Response = await starknet.devnet.flush(); const message_payload = flushL2Response.consumed_messages.from_l2[0].payload; // Proposal data can either be extracted from the message sent to L1 (as done here) or pulled from the contract directly - const [proposal, forVotes, againstVotes, abstainVotes] = extractMessagePayload(message_payload); + const [proposalId, proposal, votes] = extractMessagePayload(message_payload); // For some reason CI fails with revertedWith('InvalidProposalStatus') but works locally. await expect( l1AvatarExecutionStrategy.execute( space.address, + proposalId, proposal, - forVotes, - againstVotes, - abstainVotes, + votes, executionHash, [proposalTx], ), @@ -895,13 +881,12 @@ describe('L1 Avatar Execution', function () { value: 0, data: '0x22', operation: 0, - salt: 1, }; const abiCoder = new ethers.utils.AbiCoder(); const executionHash = ethers.utils.keccak256( abiCoder.encode( - ['tuple(address to, uint256 value, bytes data, uint8 operation, uint256 salt)[]'], + ['tuple(address to, uint256 value, bytes data, uint8 operation)[]'], [[proposalTx]], ), ); diff --git a/tests/utils.ts b/tests/utils.ts index 8c5df7d4..be101cbf 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -42,29 +42,16 @@ export async function safeWithL1AvatarExecutionStrategySetup( 'L1AvatarExecutionStrategyMockMessaging', ); - //deploying singleton master contract - const masterL1AvatarExecutionStrategy = await L1AvatarExecutionStrategyFactory.deploy( - '0x0000000000000000000000000000000000000001', - '0x0000000000000000000000000000000000000001', - '0x0000000000000000000000000000000000000001', - 1, - [], - 0, - ); - const encodedInitParams = ethers.utils.defaultAbiCoder.encode( - ['address', 'address', 'address', 'uint256', 'uint256[]', 'uint256'], - [ - safeSigner.address, - safe.address, - starknetCoreAddress, - ethRelayerAddress, - [spaceAddress], - quorum, - ], - ); + // Deploying the singleton master contract (not initialized) + const masterL1AvatarExecutionStrategy = await L1AvatarExecutionStrategyFactory.deploy(); const initData = masterL1AvatarExecutionStrategy.interface.encodeFunctionData('setUp', [ - encodedInitParams, + safeSigner.address, + safe.address, + starknetCoreAddress, + ethRelayerAddress, + [spaceAddress], + quorum, ]); const masterCopyAddress = masterL1AvatarExecutionStrategy.address @@ -118,34 +105,43 @@ export async function increaseEthBlockchainTime(networkUrl: string, seconds: num export function extractMessagePayload( message_payload: any, -): [proposal: any, forVotes: bigint, againstVotes: bigint, abstainVotes: bigint] { +): [proposalId: any, proposal: any, votes: any] { + const proposalId = uint256.uint256ToBN({ + low: message_payload[1], + high: message_payload[2], + }); const proposal = { - startTimestamp: message_payload[1], - minEndTimestamp: message_payload[2], - maxEndTimestamp: message_payload[3], - finalizationStatus: message_payload[4], - executionPayloadHash: message_payload[5], - executionStrategy: message_payload[6], - authorAddressType: message_payload[7], - author: message_payload[8], + startTimestamp: message_payload[3], + minEndTimestamp: message_payload[4], + maxEndTimestamp: message_payload[5], + finalizationStatus: message_payload[6], + executionPayloadHash: message_payload[7], + executionStrategy: message_payload[8], + authorAddressType: message_payload[9], + author: message_payload[10], activeVotingStrategies: uint256.uint256ToBN({ - low: message_payload[9], - high: message_payload[10], + low: message_payload[11], + high: message_payload[12], }), }; const forVotes = uint256.uint256ToBN({ - low: message_payload[11], - high: message_payload[12], - }); - const againstVotes = uint256.uint256ToBN({ low: message_payload[13], high: message_payload[14], }); - const abstainVotes = uint256.uint256ToBN({ + const againstVotes = uint256.uint256ToBN({ low: message_payload[15], high: message_payload[16], }); - return [proposal, forVotes, againstVotes, abstainVotes]; + const abstainVotes = uint256.uint256ToBN({ + low: message_payload[17], + high: message_payload[18], + }); + const votes = { + votesFor: forVotes, + votesAgainst: againstVotes, + votesAbstain: abstainVotes, + } + return [proposalId, proposal, votes]; } // From sx.js