From 5eccb746dd4aa7560d2b002f3e8e093d3a6f259c Mon Sep 17 00:00:00 2001 From: Orland0x <37511817+Orland0x@users.noreply.github.com> Date: Tue, 14 Jun 2022 14:00:07 +0100 Subject: [PATCH] few updates (#159) * merged files * merged space from develop * updated tests * single slot test with slot key verif * formatting * fixed more tests * fixed more tests * single slot strategy added * merged quorum stuff * revamped create proposal * fixed create vote * updated eth tx auth * zodiac test fixes * zodiac test revamp * updates * zodiac updates * fixed single slot proof strat test * Update README.md * Update README.md * fixed controller test * fixed executor whitelist test * fixed whitelist voting strategytest * more merge fixes * fix l1 tests * Delete vanilla_space.ts * Delete vanilla_authenticator.ts * replaced hardcoded vals with random ones in tests * increased timeout * OZ naming convention * OZ naming convention * Delete vanilla.cairo * Delete whitelist.cairo * Delete vanilla.cairo * Delete vanilla.cairo * Delete test_words.cairo * Delete test_array2d.cairo * Delete space.cairo * Update README.md * Update README.md * removed excess imports * Delete contracts/starknet/authenticators directory * Delete contracts/starknet/interfaces directory * GA tests (#153) * Bump ethers from 5.6.7 to 5.6.8 (#147) Bumps [ethers](https://github.com/ethers-io/ethers.js/tree/HEAD/packages/ethers) from 5.6.7 to 5.6.8. - [Release notes](https://github.com/ethers-io/ethers.js/releases) - [Changelog](https://github.com/ethers-io/ethers.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/ethers-io/ethers.js/commits/v5.6.8/packages/ethers) --- updated-dependencies: - dependency-name: ethers dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump typescript from 4.6.4 to 4.7.2 (#146) Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.6.4 to 4.7.2. - [Release notes](https://github.com/Microsoft/TypeScript/releases) - [Commits](https://github.com/Microsoft/TypeScript/compare/v4.6.4...v4.7.2) --- updated-dependencies: - dependency-name: typescript dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add starknet auth (#138) * Update to 0.8.1 and devnet 0.2.1; Format * Add execute lib; Switch to authenticate method * Add felt_to_uint256; Add starknet_tx auth * Use felt instead of u256 * Add test for starknet tx auth * Add starknet_tx_auth and starknet_account_auth; blocked by compilation on starknet_account_auth * Remove starknet_account test; Rename starknet_account to starknet_sig * Add comment about hash * Update to 0.8.2 * Add voting_strategy_params_all to setup functions * Bump npm from 8.10.0 to 8.11.0 (#149) Bumps [npm](https://github.com/npm/cli) from 8.10.0 to 8.11.0. - [Release notes](https://github.com/npm/cli/releases) - [Changelog](https://github.com/npm/cli/blob/latest/CHANGELOG.md) - [Commits](https://github.com/npm/cli/compare/v8.10.0...v8.11.0) --- updated-dependencies: - dependency-name: npm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * renaming tests * renamed cairo contracts * fixed starknet tx auth test * formatting * updated starknet hardhat * fixed account import Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: pscott <30843220+pscott@users.noreply.github.com> * Update tests.yml * Delete contracts/starknet/authenticators directory * Delete starknet_sig.cairo * Delete starknet_tx.cairo * Delete eth_tx_auth.ts * Delete zodiac.ts * Delete executor_whitelist.ts * Delete starknet_tx_auth.ts * Delete vanilla_authenticator.ts * Delete test/starknet/shared directory * updated Stark Tx auth test * use lite mode for devnet * add timeout for array 2d test * increased timeouts * fixed zodiac test * fixed zodiac module test * fixed hex equivlance issue * Bump @types/node from 17.0.35 to 17.0.36 (#156) (#158) Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 17.0.35 to 17.0.36. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * use general address type * updated starknet tx auth test * use felt to uint256 from cairo common * updated setup * deployment script * formatting * fixd vuln with execute import * added deployment script to package.json * updated readme * automatic formatting for deployments json * Update README.md Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: pscott <30843220+pscott@users.noreply.github.com> --- README.md | 23 ++- .../starknet/Authenticators/StarkSig.cairo | 1 - .../starknet/Authenticators/StarkTx.cairo | 1 - .../starknet/Authenticators/Vanilla.cairo | 2 - .../starknet/Interfaces/IVotingStrategy.cairo | 4 +- contracts/starknet/Space.cairo | 16 +- .../VotingStrategies/SingleSlotProof.cairo | 4 +- .../starknet/VotingStrategies/Vanilla.cairo | 4 +- .../starknet/VotingStrategies/Whitelist.cairo | 10 +- contracts/starknet/lib/execute.cairo | 2 - contracts/starknet/lib/felt_to_uint256.cairo | 23 --- contracts/starknet/lib/general_address.cairo | 4 + contracts/starknet/lib/proposal.cairo | 1 - contracts/starknet/lib/slot_key.cairo | 23 +-- contracts/starknet/lib/vote.cairo | 1 - deployments/goerli.json | 9 - deployments/goerli1.json | 33 ++++ package.json | 10 +- scripts/deploy.sh | 43 ----- scripts/deployTestSpace.ts | 171 +++++++++++++++++ test/crosschain/EthTxAuth.test.ts | 42 ++--- test/crosschain/ZodiacExecution.test.ts | 19 +- test/shared/constants.ts | 5 + test/shared/setup.ts | 87 +++++---- test/starknet/ExecutorWhitelist.test.ts | 24 ++- test/starknet/Space.test.ts | 14 +- test/starknet/StarkTxAuth.test.ts | 176 ++++++++++-------- tsconfig.json | 27 +-- yarn.lock | 33 ++-- 29 files changed, 472 insertions(+), 340 deletions(-) delete mode 100644 contracts/starknet/lib/felt_to_uint256.cairo create mode 100644 contracts/starknet/lib/general_address.cairo delete mode 100644 deployments/goerli.json create mode 100644 deployments/goerli1.json delete mode 100755 scripts/deploy.sh create mode 100644 scripts/deployTestSpace.ts create mode 100644 test/shared/constants.ts diff --git a/README.md b/README.md index 2639b34a..4cc9c76f 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,6 @@ contracts │ │ ├─ array2d.cairo — "For handling 2 dimensional arrays" │ │ ├─ choice.cairo — "The set of choices one can make for a vote" │ │ ├─ eth_address.cairo — "Ethereum address type" -│ │ ├─ felt_to_uint256.cairo — "Convert a felt to a uint256" │ │ ├─ hash_array.cairo — "Wrapper function for pedersen hashing arrays" │ │ ├─ proposal.cairo — "Proposal metadata type" │ │ ├─ proposal_info.cairo — "Proposal vote data type" @@ -43,17 +42,16 @@ contracts │ └─ Space.cairo - "The core contract for Snapshot X" └─ ethereum ├─ Interfaces - │ └─ IStarknetCore.sol — "Authenticate user via an Ethereum transaction" + │ └─ IStarknetCore.sol — "Interface of the StarkNet core contract" ├─ StarkNetCommit - │ └─ StarknetCommit.sol — "Authenticate user via an Ethereum transaction" + │ └─ StarknetCommit.sol — "Commits a hash to StarkNet required for Ethereum transaction authentication" ├─ ZodiacModule - │ ├─ ProposalRelayer.sol — "Authenticate user via an Ethereum transaction" - │ ├─ SnapshotXL1Executor.sol — "Authenticate user via an Ethereum transaction" - │ └─ deps.sol — "No authentication of users" + │ ├─ ProposalRelayer.sol — "Provides functionality for recieving proposal data from StarkNet" + │ └─ SnapshotXL1Executor.sol — "Execute proposal transactions using a Gnosis Safe" └─ TestContracts - ├─ MockStarknetMessaging.sol — "Authenticate user via an Ethereum transaction" - ├─ NamedStorage.sol — "Authenticate user via an Ethereum transaction" - └─ StarknetMessaging.sol — "No authentication of users" + ├─ MockStarknetMessaging.sol — "Mock StarkNet core contract for testing purposes" + ├─ NamedStorage.sol — "Storage library" + └─ StarknetMessaging.sol — "StarkNet core contract" ``` @@ -84,6 +82,13 @@ yarn compile # or yarn compile:l2 to just compile cairo contracts ``` +### Deploy to Alpha Goerli: + +```bash +yarn deploy:goerli +``` +Will deploy an example space contract and a set of authenticators, voting strategies and execution strategies to the alpha goerli testnet. + ### Testing Tests are separated into three categories: diff --git a/contracts/starknet/Authenticators/StarkSig.cairo b/contracts/starknet/Authenticators/StarkSig.cairo index 89cff933..8f312cd5 100644 --- a/contracts/starknet/Authenticators/StarkSig.cairo +++ b/contracts/starknet/Authenticators/StarkSig.cairo @@ -1,7 +1,6 @@ %lang starknet from contracts.starknet.lib.execute import execute -from contracts.starknet.lib.felt_to_uint256 import felt_to_uint256 from starkware.starknet.common.syscalls import get_caller_address from starkware.cairo.common.cairo_builtins import BitwiseBuiltin from starkware.cairo.common.math import assert_not_zero diff --git a/contracts/starknet/Authenticators/StarkTx.cairo b/contracts/starknet/Authenticators/StarkTx.cairo index 289edb12..99df307e 100644 --- a/contracts/starknet/Authenticators/StarkTx.cairo +++ b/contracts/starknet/Authenticators/StarkTx.cairo @@ -1,6 +1,5 @@ %lang starknet from contracts.starknet.lib.execute import execute -from contracts.starknet.lib.felt_to_uint256 import felt_to_uint256 from starkware.starknet.common.syscalls import get_caller_address from starkware.cairo.common.cairo_builtins import BitwiseBuiltin from starkware.cairo.common.uint256 import uint256_eq diff --git a/contracts/starknet/Authenticators/Vanilla.cairo b/contracts/starknet/Authenticators/Vanilla.cairo index cdb07118..8960b962 100644 --- a/contracts/starknet/Authenticators/Vanilla.cairo +++ b/contracts/starknet/Authenticators/Vanilla.cairo @@ -6,8 +6,6 @@ from contracts.starknet.lib.execute import execute func authenticate{syscall_ptr : felt*, range_check_ptr}( target : felt, function_selector : felt, calldata_len : felt, calldata : felt* ) -> (): - # TODO: Actually verify the signature - # Call the contract execute(target, function_selector, calldata_len, calldata) diff --git a/contracts/starknet/Interfaces/IVotingStrategy.cairo b/contracts/starknet/Interfaces/IVotingStrategy.cairo index 4b352b66..45536032 100644 --- a/contracts/starknet/Interfaces/IVotingStrategy.cairo +++ b/contracts/starknet/Interfaces/IVotingStrategy.cairo @@ -1,13 +1,13 @@ %lang starknet -from contracts.starknet.lib.eth_address import EthAddress +from contracts.starknet.lib.general_address import Address from starkware.cairo.common.uint256 import Uint256 @contract_interface namespace IVotingStrategy: func get_voting_power( block : felt, - voter_address : EthAddress, + voter_address : Address, params_len : felt, params : felt*, user_params_len : felt, diff --git a/contracts/starknet/Space.cairo b/contracts/starknet/Space.cairo index 29d2cb43..e86b3651 100644 --- a/contracts/starknet/Space.cairo +++ b/contracts/starknet/Space.cairo @@ -16,7 +16,7 @@ from starkware.cairo.common.math import ( from contracts.starknet.Interfaces.IVotingStrategy import IVotingStrategy from contracts.starknet.Interfaces.IExecutionStrategy import IExecutionStrategy -from contracts.starknet.lib.eth_address import EthAddress +from contracts.starknet.lib.general_address import Address from contracts.starknet.lib.proposal import Proposal from contracts.starknet.lib.proposal_info import ProposalInfo from contracts.starknet.lib.vote import Vote @@ -88,7 +88,7 @@ func executed_proposals_store(proposal_id : felt) -> (executed : felt): end @storage_var -func vote_registry_store(proposal_id : felt, voter_address : EthAddress) -> (vote : Vote): +func vote_registry_store(proposal_id : felt, voter_address : Address) -> (vote : Vote): end @storage_var @@ -102,7 +102,7 @@ end @event func proposal_created( proposal_id : felt, - proposer_address : EthAddress, + proposer_address : Address, proposal : Proposal, metadata_uri_len : felt, metadata_uri : felt*, @@ -112,7 +112,7 @@ func proposal_created( end @event -func vote_created(proposal_id : felt, voter_address : EthAddress, vote : Vote): +func vote_created(proposal_id : felt, voter_address : Address, vote : Vote): end @event @@ -392,7 +392,7 @@ end # TODO: In the future we will need to transition to an array of `voter_address` because they might be different for different voting strategies. func get_cumulative_voting_power{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}( current_timestamp : felt, - voter_address : EthAddress, + voter_address : Address, used_voting_strategies_len : felt, used_voting_strategies : felt*, user_voting_strategy_params_all : Immutable2DArray, @@ -660,7 +660,7 @@ end @external func vote{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr : felt}( - voter_address : EthAddress, + voter_address : Address, proposal_id : felt, choice : felt, used_voting_strategies_len : felt, @@ -744,7 +744,7 @@ end @external func propose{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr : felt}( - proposer_address : EthAddress, + proposer_address : Address, execution_hash : Uint256, metadata_uri_len : felt, metadata_uri : felt*, @@ -988,7 +988,7 @@ end @view func get_vote_info{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr : felt}( - voter_address : EthAddress, proposal_id : felt + voter_address : Address, proposal_id : felt ) -> (vote : Vote): return vote_registry_store.read(proposal_id, voter_address) end diff --git a/contracts/starknet/VotingStrategies/SingleSlotProof.cairo b/contracts/starknet/VotingStrategies/SingleSlotProof.cairo index dd4b06c6..3f8aba1f 100644 --- a/contracts/starknet/VotingStrategies/SingleSlotProof.cairo +++ b/contracts/starknet/VotingStrategies/SingleSlotProof.cairo @@ -5,7 +5,7 @@ from starkware.cairo.common.uint256 import Uint256, uint256_add from starkware.cairo.common.math import unsigned_div_rem, assert_nn_le from contracts.starknet.fossil.contracts.starknet.types import StorageSlot -from contracts.starknet.lib.eth_address import EthAddress +from contracts.starknet.lib.general_address import Address from contracts.starknet.lib.slot_key import get_slot_key from contracts.starknet.lib.words import words_to_uint256 @@ -44,7 +44,7 @@ func get_voting_power{ syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr, bitwise_ptr : BitwiseBuiltin* }( block : felt, - voter_address : EthAddress, + voter_address : Address, params_len : felt, params : felt*, user_params_len : felt, diff --git a/contracts/starknet/VotingStrategies/Vanilla.cairo b/contracts/starknet/VotingStrategies/Vanilla.cairo index 6c2ed1c4..c2a97299 100644 --- a/contracts/starknet/VotingStrategies/Vanilla.cairo +++ b/contracts/starknet/VotingStrategies/Vanilla.cairo @@ -1,13 +1,13 @@ %lang starknet from starkware.cairo.common.uint256 import Uint256 -from contracts.starknet.lib.eth_address import EthAddress +from contracts.starknet.lib.general_address import Address # Returns a voting power of 1 for every address it is queried with. @view func get_voting_power{range_check_ptr}( block : felt, - voter_address : EthAddress, + voter_address : Address, params_len : felt, params : felt*, user_params_len : felt, diff --git a/contracts/starknet/VotingStrategies/Whitelist.cairo b/contracts/starknet/VotingStrategies/Whitelist.cairo index 50fbb6c8..de8a3732 100644 --- a/contracts/starknet/VotingStrategies/Whitelist.cairo +++ b/contracts/starknet/VotingStrategies/Whitelist.cairo @@ -2,14 +2,14 @@ from starkware.cairo.common.uint256 import Uint256, uint256_check from starkware.cairo.common.cairo_builtins import HashBuiltin -from contracts.starknet.lib.eth_address import EthAddress +from contracts.starknet.lib.general_address import Address @storage_var -func whitelist(address : EthAddress) -> (voting_power : Uint256): +func whitelist(address : Address) -> (voting_power : Uint256): end @event -func whitelisted(address : EthAddress, voting_power : Uint256): +func whitelisted(address : Address, voting_power : Uint256): end func register_whitelist{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr : felt}( @@ -18,7 +18,7 @@ func register_whitelist{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_ if _whitelist_len == 0: return () else: - let address = EthAddress(_whitelist[0]) + let address = Address(_whitelist[0]) # Add it to the whitelist let voting_power = Uint256(_whitelist[1], _whitelist[2]) @@ -47,7 +47,7 @@ end @view func get_voting_power{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr : felt}( block : felt, - voter_address : EthAddress, + voter_address : Address, params_len : felt, params : felt*, user_params_len : felt, diff --git a/contracts/starknet/lib/execute.cairo b/contracts/starknet/lib/execute.cairo index e61340f1..c354e5ee 100644 --- a/contracts/starknet/lib/execute.cairo +++ b/contracts/starknet/lib/execute.cairo @@ -1,8 +1,6 @@ -%lang starknet from starkware.starknet.common.syscalls import call_contract # Forwards `data` to `target` without verifying anything. -@external func execute{syscall_ptr : felt*, range_check_ptr}( target : felt, function_selector : felt, calldata_len : felt, calldata : felt* ) -> (): diff --git a/contracts/starknet/lib/felt_to_uint256.cairo b/contracts/starknet/lib/felt_to_uint256.cairo deleted file mode 100644 index 2a31fb60..00000000 --- a/contracts/starknet/lib/felt_to_uint256.cairo +++ /dev/null @@ -1,23 +0,0 @@ -from starkware.cairo.common.cairo_builtins import BitwiseBuiltin -from starkware.cairo.common.math import unsigned_div_rem -from starkware.cairo.common.bitwise import bitwise_and -from starkware.cairo.common.uint256 import Uint256 - -const MASK_LOW = 2 ** 128 - 1 -const MASK_HIGH = 2 ** 251 - 2 ** 128 - -const SHIFT_8 = 2 ** 8 -const SHIFT_120 = 2 ** 120 - -# Convert a felt to 2 128 bit words returned as a uint256. -func felt_to_uint256{bitwise_ptr : BitwiseBuiltin*, range_check_ptr}(value : felt) -> ( - uint256 : Uint256 -): - let (low) = bitwise_and(value, MASK_LOW) - - let (t1) = bitwise_and(value, MASK_HIGH) - let (t1, _) = unsigned_div_rem(t1, SHIFT_120) - let (high, _) = unsigned_div_rem(t1, SHIFT_8) - - return (Uint256(low=low, high=high)) -end diff --git a/contracts/starknet/lib/general_address.cairo b/contracts/starknet/lib/general_address.cairo new file mode 100644 index 00000000..676a59b2 --- /dev/null +++ b/contracts/starknet/lib/general_address.cairo @@ -0,0 +1,4 @@ +# Generalized type used to represent addresses in Snapshot X. Eg Ethereum, Starknet, etc. +struct Address: + member value : felt +end diff --git a/contracts/starknet/lib/proposal.cairo b/contracts/starknet/lib/proposal.cairo index 0bb38609..5a61c4f1 100644 --- a/contracts/starknet/lib/proposal.cairo +++ b/contracts/starknet/lib/proposal.cairo @@ -1,4 +1,3 @@ -from contracts.starknet.lib.eth_address import EthAddress from starkware.cairo.common.uint256 import Uint256 struct Proposal: diff --git a/contracts/starknet/lib/slot_key.cairo b/contracts/starknet/lib/slot_key.cairo index 6c588cd1..932ebce8 100644 --- a/contracts/starknet/lib/slot_key.cairo +++ b/contracts/starknet/lib/slot_key.cairo @@ -1,25 +1,20 @@ -from starkware.cairo.common.cairo_builtins import BitwiseBuiltin from starkware.cairo.common.alloc import alloc from starkware.cairo.common.keccak import unsafe_keccak from starkware.cairo.common.uint256 import Uint256 -from starknet.lib.felt_to_uint256 import felt_to_uint256 +from starkware.cairo.common.math import split_felt # Returns the EVM slot key for mappings (key can be any value type) -# For more information, refer to the following repo: -# https://github.com/snapshot-labs/evm-slot-key-verification # UNSAFE: This is not safe to use in production code due to unsafe keccak - waiting for safe version -func get_slot_key{bitwise_ptr : BitwiseBuiltin*, range_check_ptr}( - slot_index : felt, mapping_key : felt -) -> (slot_key : Uint256): +func get_slot_key{range_check_ptr}(slot_index : felt, mapping_key : felt) -> (slot_key : Uint256): alloc_locals let (encoded_array : felt*) = alloc() - let (slot_index_uint256) = felt_to_uint256(slot_index) - let (mapping_key_uint256) = felt_to_uint256(mapping_key) - encoded_array[0] = mapping_key_uint256.high - encoded_array[1] = mapping_key_uint256.low - encoded_array[2] = slot_index_uint256.high - encoded_array[3] = slot_index_uint256.low - let (low, high) = unsafe_keccak(encoded_array, 16 * 4) + let (slot_index_high, slot_index_low) = split_felt(slot_index) + let (mapping_key_high, mapping_key_low) = split_felt(mapping_key) + encoded_array[0] = mapping_key_high + encoded_array[1] = mapping_key_low + encoded_array[2] = slot_index_high + encoded_array[3] = slot_index_low + let (low, high) = unsafe_keccak(encoded_array, 64) let slot_key = Uint256(low=low, high=high) return (slot_key) end diff --git a/contracts/starknet/lib/vote.cairo b/contracts/starknet/lib/vote.cairo index 502fb77c..89870442 100644 --- a/contracts/starknet/lib/vote.cairo +++ b/contracts/starknet/lib/vote.cairo @@ -1,6 +1,5 @@ %lang starknet -from contracts.starknet.lib.eth_address import EthAddress from starkware.cairo.common.uint256 import Uint256 struct Vote: diff --git a/deployments/goerli.json b/deployments/goerli.json deleted file mode 100644 index 40bcc48e..00000000 --- a/deployments/goerli.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "authenticators": { - "vanilla": "0x063d3c1c93411131b65491f216301263e6071ef0df02ab800cdd7748ddedcecf" - }, - "voting_strategies": { - "vanilla": "0x06a7b4259999163b09d9e2480ccbefee5c1cc9672fa8416411e485e502f8ee95" - }, - "space": "0x0625dc1290b6e936be5f1a3e963cf629326b1f4dfd5a56738dea98e1ad31b7f3" -} diff --git a/deployments/goerli1.json b/deployments/goerli1.json new file mode 100644 index 00000000..4c0d5913 --- /dev/null +++ b/deployments/goerli1.json @@ -0,0 +1,33 @@ +{ + "space": { + "address": "0x56f0102b537fae4a9f94c362473d7f03025e92af246502074d9f204c027058b", + "authenticators": { + "StarkTx": "0x327d3a82cf938e7dcef065db5d3f4c40d2b495b27912e352817cf3da41643f9", + "Vanilla": "0x28511c7039691e7298c92b753e28d79ebf8253acc0fa508bb159dd12adea0b6" + }, + "controller": "0x0070d911463b2cb48de8bfec826483631cdc492a6c5798917651297769fc9d68", + "executionStrategies": { + "Vanilla": "0x5d4a61e5ea572b1e956c19ca76678336c2e0472a7988b0b5979fa18719b5652", + "zodiacRelayer": "0x5c512fbf7f4dc97bd2a68e7096968ce8ecd65d42583cbacaf3fdcc7a1800f80" + }, + "maxVotingDuration": "0x7d0", + "minVotingDuration": "0x0", + "name": "Test space", + "proposalThreshold": "0x1", + "quorum": "0x1", + "votingStrategies": { + "SingleSlotProof": { + "address": "0x78f994cdf794bebd68027ef9e2ee0bf309983d87755efb4f5bded8d26980514", + "parameters": [ + "0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9", + "0x0" + ] + }, + "Vanilla": { + "address": "0x61b900e2c3b8beb266e1fe9abe837a9b8276cac39509b3b25ad10a20767763a", + "parameters": [ + ] + } + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index 46fdabb8..8f4d0feb 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "test:l2:ci": "concurrently './scripts/chain-l2.sh' './scripts/test-l2.sh'", "test:crosschain": "'./scripts/test-crosschain.sh'", "test:crosschain:ci": "concurrently './scripts/chain.sh' './scripts/test-crosschain.sh'", + "deploy:goerli": "yarn hardhat run ./scripts/deployTestSpace.ts", "chain:l1": "hardhat node", "chain:l2": "starknet-devnet -p 8000 --lite-mode", "chain": "concurrently 'yarn chain:l1' 'yarn chain:l2'", @@ -22,7 +23,8 @@ "check-format:l2": "cairo-format -c --one_item_per_line contracts/starknet/**/*.cairo && cairo-format -c --one_item_per_line contracts/starknet/*.cairo", "format:ts": "eslint . --ext .ts --fix", "check-format:ts": "eslint . --ext .ts", - "format": "yarn format:l1 && yarn format:l2 && yarn format:ts", + "format:json": "json-format ./deployments/*.json", + "format": "yarn format:l1 && yarn format:l2 && yarn format:ts && yarn format:json", "check-format": "yarn check-format:l1 && yarn check-format:l2 && yarn check-format:ts" }, "dependencies": { @@ -32,8 +34,10 @@ "concurrently": "^7.2.1", "ethereumjs-util": "^7.1.5", "install": "^0.13.0", - "npm": "^8.12.1", - "starknet": "^2.5.1", + "json-format-cli": "^1.1.1", + "npm": "^8.11.0", + "prettyjson": "^1.2.5", + "starknet": "^3.9.0", "sx-api": "snapshot-labs/sx-api", "wait-on": "^6.0.1", "yargs": "^17.5.0" diff --git a/scripts/deploy.sh b/scripts/deploy.sh deleted file mode 100755 index 32e7bfa1..00000000 --- a/scripts/deploy.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -# Constants -VOTING_DELAY=0 -VOTING_DURATION=100000000 -# Threshold should be two numbers because Uint256 has two members. We're just using the lowest number here. -THRESHOLD=1 - -if [ $1 == "local" ]; then - NETWORK_OPTION="--gateway-url http://localhost:8000" - FILE="local.json" -else - # Defaults to alpha - NETWORK_OPTION="--starknet-network alpha" - FILE="goerli.json" -fi -echo "Option: $NETWORK_OPTION" - -FILE="deployed_contracts/${FILE}" - -# Compile everything -echo "Compiling..." -yarn compile:l2 -echo "✅ Compiilation done" - -echo "Deploying auth contract..." -AUTH=$(hardhat starknet-deploy ${NETWORK_OPTION} starknet-artifacts/contracts/starknet/authenticator/authenticator.cairo/authenticator.json | grep 'Contract address' | tail -c 67) -echo "✅ Auth: ${AUTH}" -echo "Deploying strategy contract" -STRATEGY=$(hardhat starknet-deploy ${NETWORK_OPTION} starknet-artifacts/contracts/starknet/voting_strategies/vanilla_voting_strategy.cairo/vanilla_voting_strategy.json | grep 'Contract address' | tail -c 67) -echo "✅ Strategy: ${STRATEGY}" -echo "Deploying space contract" -SPACE=$(hardhat starknet-deploy ${NETWORK_OPTION} --inputs "${VOTING_DELAY} ${VOTING_DURATION} ${THRESHOLD} 0 ${STRATEGY} ${AUTH}" starknet-artifacts/contracts/starknet/space.cairo/space.json | grep 'Contract address' | tail -c 67) -echo "✅ Space: ${SPACE}" - -JSON="{\n -\t\"authenticators\": {\n\t\t\"vanilla\": \"${AUTH}\"\n\t},\n -\t\"voting_strategies\": {\n\t\t\"vanilla\": \"${STRATEGY}\"\n\t},\n -\t\"space\": \"${SPACE}\"\n}" - -echo $JSON > $FILE - -echo "✅ Wrote the latest contracts in ${FILE}" diff --git a/scripts/deployTestSpace.ts b/scripts/deployTestSpace.ts new file mode 100644 index 00000000..51fdc67c --- /dev/null +++ b/scripts/deployTestSpace.ts @@ -0,0 +1,171 @@ +import fs from 'fs'; +import { + Contract, + Account, + defaultProvider, + ec, + encode, + hash, + json, + number, + stark, + RawCalldata, +} from 'starknet'; +import { SplitUint256 } from '../test/shared/types'; +import { flatten2DArray } from '../test/shared/helpers'; + +async function main() { + const compiledVanillaAuthenticator = json.parse( + fs + .readFileSync( + './starknet-artifacts/contracts/starknet/Authenticators/Vanilla.cairo/Vanilla.json' + ) + .toString('ascii') + ); + const compiledStarkTxAuthenticator = json.parse( + fs + .readFileSync( + './starknet-artifacts/contracts/starknet/Authenticators/StarkTx.cairo/StarkTx.json' + ) + .toString('ascii') + ); + const compiledVanillaVotingStrategy = json.parse( + fs + .readFileSync( + './starknet-artifacts/contracts/starknet/VotingStrategies/Vanilla.cairo/Vanilla.json' + ) + .toString('ascii') + ); + const compiledSingleSlotProofVotingStrategy = json.parse( + fs + .readFileSync( + './starknet-artifacts/contracts/starknet/VotingStrategies/SingleSlotProof.cairo/SingleSlotProof.json' + ) + .toString('ascii') + ); + const compiledVanillaExecutionStrategy = json.parse( + fs + .readFileSync( + './starknet-artifacts/contracts/starknet/ExecutionStrategies/Vanilla.cairo/Vanilla.json' + ) + .toString('ascii') + ); + const compiledZodiacRelayerExecutionStrategy = json.parse( + fs + .readFileSync( + './starknet-artifacts/contracts/starknet/ExecutionStrategies/ZodiacRelayer.cairo/ZodiacRelayer.json' + ) + .toString('ascii') + ); + const compiledSpace = json.parse( + fs + .readFileSync('./starknet-artifacts/contracts/starknet/Space.cairo/Space.json') + .toString('ascii') + ); + + const deployTxs = [ + defaultProvider.deployContract({ contract: compiledVanillaAuthenticator }), + defaultProvider.deployContract({ contract: compiledStarkTxAuthenticator }), + defaultProvider.deployContract({ contract: compiledVanillaVotingStrategy }), + defaultProvider.deployContract({ contract: compiledSingleSlotProofVotingStrategy }), + defaultProvider.deployContract({ contract: compiledVanillaExecutionStrategy }), + defaultProvider.deployContract({ contract: compiledZodiacRelayerExecutionStrategy }), + ]; + const responses = await Promise.all(deployTxs); + const vanillaAuthenticatorAddress = responses[0].address!; + const starkTxAuthenticatorAddress = responses[1].address!; + const vanillaVotingStrategyAddress = responses[2].address!; + const singleSlotProofVotingStrategyAddress = responses[3].address!; + const vanillaExecutionStrategyAddress = responses[4].address!; + const zodiacRelayerExecutionStrategyAddress = responses[5].address!; + + console.log(responses); + + const votingDelay = BigInt(0); + const minVotingDuration = BigInt(0); + const maxVotingDuration = BigInt(2000); + const votingStrategies: bigint[] = [ + BigInt(vanillaVotingStrategyAddress), + BigInt(singleSlotProofVotingStrategyAddress), + ]; + const votingStrategyParams: bigint[][] = [ + [], + [BigInt('0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9'), BigInt(0)], + ]; // vanilla and Aave token voting + const votingStrategyParamsFlat: bigint[] = flatten2DArray(votingStrategyParams); + const authenticators: bigint[] = [ + BigInt(vanillaAuthenticatorAddress), + BigInt(starkTxAuthenticatorAddress), + ]; + const executors: bigint[] = [ + BigInt(vanillaExecutionStrategyAddress), + BigInt(zodiacRelayerExecutionStrategyAddress), + ]; + const quorum: SplitUint256 = SplitUint256.fromUint(BigInt(1)); // Quorum of one for the vanilla test + const proposalThreshold: SplitUint256 = SplitUint256.fromUint(BigInt(1)); // Proposal threshold of 1 for the vanilla test + const controllerAddress = '0x0070d911463b2cb48de8bfec826483631cdc492a6c5798917651297769fc9d68'; // Controller address (orlando's argent x) + + const spaceDeploymentCalldata: bigint[] = [ + votingDelay, + minVotingDuration, + maxVotingDuration, + proposalThreshold.low, + proposalThreshold.high, + BigInt(controllerAddress), + quorum.low, + quorum.high, + BigInt(votingStrategyParamsFlat.length), + ...votingStrategyParamsFlat, + BigInt(votingStrategies.length), + ...votingStrategies, + BigInt(authenticators.length), + ...authenticators, + BigInt(executors.length), + ...executors, + ]; + const spaceDeploymentCalldataHex = spaceDeploymentCalldata.map((x) => '0x' + x.toString(16)); + const spaceResponse = await defaultProvider.deployContract({ + contract: compiledSpace, + constructorCalldata: spaceDeploymentCalldataHex, + }); + + const spaceAddress = spaceResponse.address!; + + const deployments = { + space: { + name: 'Test space', + address: spaceAddress, + controller: controllerAddress, + minVotingDuration: '0x' + minVotingDuration.toString(16), + maxVotingDuration: '0x' + maxVotingDuration.toString(16), + proposalThreshold: proposalThreshold.toHex(), + quorum: quorum.toHex(), + authenticators: { + Vanilla: vanillaAuthenticatorAddress, + StarkTx: starkTxAuthenticatorAddress, + }, + votingStrategies: { + Vanilla: { + address: vanillaVotingStrategyAddress, + parameters: [], + }, + SingleSlotProof: { + address: singleSlotProofVotingStrategyAddress, + parameters: ['0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', '0x0'], + }, + }, + executionStrategies: { + Vanilla: vanillaExecutionStrategyAddress, + zodiacRelayer: zodiacRelayerExecutionStrategyAddress, + }, + }, + }; + fs.writeFileSync('./deployments/goerli1.json', JSON.stringify(deployments)); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/test/crosschain/EthTxAuth.test.ts b/test/crosschain/EthTxAuth.test.ts index 2e057623..f884c690 100644 --- a/test/crosschain/EthTxAuth.test.ts +++ b/test/crosschain/EthTxAuth.test.ts @@ -2,13 +2,11 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { expect } from 'chai'; import { Contract } from 'ethers'; import { starknet, network, ethers } from 'hardhat'; -import { stark } from 'starknet'; import { StarknetContract, Account, HttpNetworkConfig } from 'hardhat/types'; import { strToShortStringArr } from '@snapshot-labs/sx'; import { createExecutionHash, getCommit, getProposeCalldata } from '../shared/helpers'; import { ethTxAuthSetup } from '../shared/setup'; - -const { getSelectorFromName } = stark; +import { PROPOSE_SELECTOR, VOTE_SELECTOR } from '../shared/constants'; // Dummy tx const tx1 = { @@ -96,15 +94,13 @@ describe('L1 interaction with Snapshot X', function () { // Committing the hash of the payload to the StarkNet Commit L1 contract await starknetCommit .connect(signer) - .commit( - getCommit(BigInt(space.address), BigInt(getSelectorFromName('propose')), proposeCalldata) - ); + .commit(getCommit(BigInt(space.address), PROPOSE_SELECTOR, proposeCalldata)); // Checking that the L1 -> L2 message has been propogated expect((await starknet.devnet.flush()).consumed_messages.from_l1).to.have.a.lengthOf(1); // Creating proposal - await ethTxAuthenticator.invoke('execute', { + await ethTxAuthenticator.invoke('authenticate', { target: BigInt(space.address), - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata, }); }); @@ -113,20 +109,18 @@ describe('L1 interaction with Snapshot X', function () { await starknet.devnet.loadL1MessagingContract(networkUrl, mockStarknetMessaging.address); await starknetCommit .connect(signer) - .commit( - getCommit(BigInt(space.address), BigInt(getSelectorFromName('propose')), proposeCalldata) - ); + .commit(getCommit(BigInt(space.address), PROPOSE_SELECTOR, proposeCalldata)); await starknet.devnet.flush(); - await ethTxAuthenticator.invoke('execute', { + await ethTxAuthenticator.invoke('authenticate', { target: BigInt(space.address), - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata, }); - // Second attempt at calling execute should fail + // Second attempt at calling authenticate should fail try { - await ethTxAuthenticator.invoke('execute', { + await ethTxAuthenticator.invoke('authenticate', { target: BigInt(space.address), - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata, }); } catch (err: any) { @@ -138,14 +132,12 @@ describe('L1 interaction with Snapshot X', function () { await starknet.devnet.loadL1MessagingContract(networkUrl, mockStarknetMessaging.address); await starknetCommit .connect(signer) - .commit( - getCommit(BigInt(space.address), BigInt(getSelectorFromName('vote')), proposeCalldata) - ); // Wrong selector + .commit(getCommit(BigInt(space.address), PROPOSE_SELECTOR, proposeCalldata)); // Wrong selector await starknet.devnet.flush(); try { - await ethTxAuthenticator.invoke('execute', { + await ethTxAuthenticator.invoke('authenticate', { target: BigInt(space.address), - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata, }); } catch (err: any) { @@ -158,14 +150,12 @@ describe('L1 interaction with Snapshot X', function () { proposeCalldata[0] = BigInt(ethers.Wallet.createRandom().address); // Random l1 address in the calldata await starknetCommit .connect(signer) - .commit( - getCommit(BigInt(space.address), BigInt(getSelectorFromName('propose')), proposeCalldata) - ); + .commit(getCommit(BigInt(space.address), PROPOSE_SELECTOR, proposeCalldata)); await starknet.devnet.flush(); try { - await ethTxAuthenticator.invoke('execute', { + await ethTxAuthenticator.invoke('authenticate', { target: BigInt(space.address), - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata, }); } catch (err: any) { diff --git a/test/crosschain/ZodiacExecution.test.ts b/test/crosschain/ZodiacExecution.test.ts index c1cef470..e8ee8c26 100644 --- a/test/crosschain/ZodiacExecution.test.ts +++ b/test/crosschain/ZodiacExecution.test.ts @@ -4,7 +4,6 @@ import { Contract } from 'ethers'; import hre, { starknet, network } from 'hardhat'; import { Choice, SplitUint256 } from '../shared/types'; import { StarknetContract, HttpNetworkConfig, Account } from 'hardhat/types'; -import { stark } from 'starknet'; import { strToShortStringArr } from '@snapshot-labs/sx'; import { zodiacRelayerSetup } from '../shared/setup'; import { @@ -13,15 +12,13 @@ import { getProposeCalldata, getVoteCalldata, } from '../shared/helpers'; +import { PROPOSE_SELECTOR, VOTE_SELECTOR } from '../shared/constants'; -const { getSelectorFromName } = stark; - -export const VITALIK_ADDRESS = BigInt('0xd8da6bf26964af9d7eed9e03e53415d37aa96045'); -export const VITALIK_STRING_ADDRESS = VITALIK_ADDRESS.toString(16); +const VITALIK_ADDRESS = 'd8da6bf26964af9d7eed9e03e53415d37aa96045'; //removed hex prefix // Dummy tx const tx1 = { - to: VITALIK_STRING_ADDRESS, + to: VITALIK_ADDRESS, value: 0, data: '0x11', operation: 0, @@ -30,7 +27,7 @@ const tx1 = { // Dummy tx 2 const tx2 = { - to: VITALIK_STRING_ADDRESS, + to: VITALIK_ADDRESS, value: 0, data: '0x22', operation: 0, @@ -131,16 +128,16 @@ describe('Create proposal, cast vote, and send execution to l1', function () { this.timeout(1200000); // -- Creates a proposal -- - await vanillaAuthenticator.invoke('execute', { + await vanillaAuthenticator.invoke('authenticate', { target: BigInt(space.address), - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata, }); // -- Casts a vote FOR -- - await vanillaAuthenticator.invoke('execute', { + await vanillaAuthenticator.invoke('authenticate', { target: BigInt(space.address), - function_selector: BigInt(getSelectorFromName('vote')), + function_selector: VOTE_SELECTOR, calldata: voteCalldata, }); diff --git a/test/shared/constants.ts b/test/shared/constants.ts new file mode 100644 index 00000000..8c4478f1 --- /dev/null +++ b/test/shared/constants.ts @@ -0,0 +1,5 @@ +import { hash } from 'starknet'; +const { getSelectorFromName } = hash; + +export const PROPOSE_SELECTOR = BigInt(getSelectorFromName('propose')); +export const VOTE_SELECTOR = BigInt(getSelectorFromName('vote')); diff --git a/test/shared/setup.ts b/test/shared/setup.ts index f8889e55..114fde68 100644 --- a/test/shared/setup.ts +++ b/test/shared/setup.ts @@ -18,7 +18,7 @@ export interface Fossil { export async function vanillaSetup() { const controller = (await starknet.deployAccount('OpenZeppelin')) as Account; const spaceFactory = await starknet.getContractFactory('./contracts/starknet/Space.cairo'); - const vanillaVotingStategyFactory = await starknet.getContractFactory( + const vanillaVotingStrategyFactory = await starknet.getContractFactory( './contracts/starknet/VotingStrategies/Vanilla.cairo' ); const vanillaAuthenticatorFactory = await starknet.getContractFactory( @@ -30,7 +30,7 @@ export async function vanillaSetup() { const deployments = [ vanillaAuthenticatorFactory.deploy(), - vanillaVotingStategyFactory.deploy(), + vanillaVotingStrategyFactory.deploy(), vanillaExecutionStrategyFactory.deploy(), ]; const contracts = await Promise.all(deployments); @@ -239,7 +239,7 @@ export async function safeWithZodiacSetup( export async function ethTxAuthSetup() { const controller = (await starknet.deployAccount('OpenZeppelin')) as Account; const spaceFactory = await starknet.getContractFactory('./contracts/starknet/Space.cairo'); - const vanillaVotingStategyFactory = await starknet.getContractFactory( + const vanillaVotingStrategyFactory = await starknet.getContractFactory( './contracts/starknet/VotingStrategies/Vanilla.cairo' ); const ethTxAuthenticatorFactory = await starknet.getContractFactory( @@ -265,7 +265,7 @@ export async function ethTxAuthSetup() { const deployments = [ ethTxAuthenticatorFactory.deploy({ starknet_commit_address: BigInt(starknetCommit.address) }), - vanillaVotingStategyFactory.deploy(), + vanillaVotingStrategyFactory.deploy(), vanillaExecutionStrategyFactory.deploy(), ]; const contracts = await Promise.all(deployments); @@ -370,7 +370,7 @@ export async function starknetAccountSetup() { const account = await starknet.deployAccount('OpenZeppelin'); const vanillaSpaceFactory = await starknet.getContractFactory('./contracts/starknet/Space.cairo'); - const vanillaVotingStategyFactory = await starknet.getContractFactory( + const vanillaVotingStrategyFactory = await starknet.getContractFactory( './contracts/starknet/VotingStrategies/Vanilla.cairo' ); const starknetAccountAuthFactory = await starknet.getContractFactory( @@ -382,7 +382,7 @@ export async function starknetAccountSetup() { const deployments = [ starknetAccountAuthFactory.deploy(), - vanillaVotingStategyFactory.deploy(), + vanillaVotingStrategyFactory.deploy(), zodiacRelayerFactory.deploy(), ]; console.log('Deploying auth, voting and zodiac relayer contracts...'); @@ -427,63 +427,60 @@ export async function starknetAccountSetup() { }; } -export async function starknetTxSetup() { - const account = await starknet.deployAccount('OpenZeppelin'); - - const vanillaSpaceFactory = await starknet.getContractFactory('./contracts/starknet/Space.cairo'); - const vanillaVotingStategyFactory = await starknet.getContractFactory( +export async function starkTxAuthSetup() { + const controller = (await starknet.deployAccount('OpenZeppelin')) as Account; + const spaceFactory = await starknet.getContractFactory('./contracts/starknet/Space.cairo'); + const vanillaVotingStrategyFactory = await starknet.getContractFactory( './contracts/starknet/VotingStrategies/Vanilla.cairo' ); - const starknetTxAuthFactory = await starknet.getContractFactory( + const starknetTxAuthenticatorFactory = await starknet.getContractFactory( './contracts/starknet/Authenticators/StarkTx.cairo' ); - const zodiacRelayerFactory = await starknet.getContractFactory( - './contracts/starknet/ExecutionStrategies/ZodiacRelayer.cairo' + const vanillaExecutionStrategyFactory = await starknet.getContractFactory( + './contracts/starknet/ExecutionStrategies/Vanilla.cairo' ); const deployments = [ - starknetTxAuthFactory.deploy(), - vanillaVotingStategyFactory.deploy(), - zodiacRelayerFactory.deploy(), + starknetTxAuthenticatorFactory.deploy(), + vanillaVotingStrategyFactory.deploy(), + vanillaExecutionStrategyFactory.deploy(), ]; - console.log('Deploying auth, voting and zodiac relayer contracts...'); const contracts = await Promise.all(deployments); - const starknetTxAuth = contracts[0] as StarknetContract; + const starknetTxAuthenticator = contracts[0] as StarknetContract; const vanillaVotingStrategy = contracts[1] as StarknetContract; - const zodiacRelayer = contracts[2] as StarknetContract; - - const voting_strategy = BigInt(vanillaVotingStrategy.address); - const authenticator = BigInt(starknetTxAuth.address); - const zodiac_relayer = BigInt(zodiacRelayer.address); - const quorum = SplitUint256.fromUint(BigInt(0)); - - const voting_strategy_params: bigint[][] = [[]]; - const voting_strategy_params_flat = flatten2DArray(voting_strategy_params); + const vanillaExecutionStrategy = contracts[2] as StarknetContract; - // This should be declared along with the other const but doing so will make the compiler unhappy as `SplitUint256` - // will be undefined for some reason? - const PROPOSAL_THRESHOLD = SplitUint256.fromUint(BigInt(1)); + const votingDelay = BigInt(0); + const minVotingDuration = BigInt(0); + const maxVotingDuration = BigInt(2000); + const votingStrategies: bigint[] = [BigInt(vanillaVotingStrategy.address)]; + const votingStrategyParams: bigint[][] = [[]]; // No params for the vanilla voting strategy + const votingStrategyParamsFlat: bigint[] = flatten2DArray(votingStrategyParams); + const authenticators: bigint[] = [BigInt(starknetTxAuthenticator.address)]; + const executors: bigint[] = [BigInt(vanillaExecutionStrategy.address)]; + const quorum: SplitUint256 = SplitUint256.fromUint(BigInt(1)); // Quorum of one for the vanilla test + const proposalThreshold: SplitUint256 = SplitUint256.fromUint(BigInt(1)); // Proposal threshold of 1 for the vanilla test console.log('Deploying space contract...'); - const vanillaSpace = (await vanillaSpaceFactory.deploy({ - _voting_delay: BigInt(0), - _min_voting_duration: BigInt(0), - _max_voting_duration: BigInt(2000), - _proposal_threshold: PROPOSAL_THRESHOLD, + const space = (await spaceFactory.deploy({ + _voting_delay: votingDelay, + _min_voting_duration: minVotingDuration, + _max_voting_duration: maxVotingDuration, + _proposal_threshold: proposalThreshold, + _controller: BigInt(controller.starknetContract.address), _quorum: quorum, - _controller: BigInt(account.starknetContract.address), - _voting_strategy_params_flat: voting_strategy_params_flat, - _voting_strategies: [voting_strategy], - _authenticators: [authenticator], - _executors: [zodiac_relayer], + _voting_strategy_params_flat: votingStrategyParamsFlat, + _voting_strategies: votingStrategies, + _authenticators: authenticators, + _executors: executors, })) as StarknetContract; console.log('deployed!'); return { - vanillaSpace, - starknetTxAuth, + space, + controller, + starknetTxAuthenticator, vanillaVotingStrategy, - zodiacRelayer, - account, + vanillaExecutionStrategy, }; } diff --git a/test/starknet/ExecutorWhitelist.test.ts b/test/starknet/ExecutorWhitelist.test.ts index b907d793..18fb1a5b 100644 --- a/test/starknet/ExecutorWhitelist.test.ts +++ b/test/starknet/ExecutorWhitelist.test.ts @@ -1,13 +1,11 @@ import { expect } from 'chai'; import { Contract } from 'ethers'; -import { stark } from 'starknet'; import { starknet, ethers } from 'hardhat'; import { strToShortStringArr } from '@snapshot-labs/sx'; import { zodiacRelayerSetup } from '../shared/setup'; import { getProposeCalldata, bytesToHex } from '../shared/helpers'; import { StarknetContract, Account } from 'hardhat/types'; - -const { getSelectorFromName } = stark; +import { PROPOSE_SELECTOR, VOTE_SELECTOR } from '../shared/constants'; describe('Whitelist testing', () => { // Contracts @@ -94,9 +92,9 @@ describe('Whitelist testing', () => { it('Should create a proposal for a whitelisted executor', async () => { { - await vanillaAuthenticator.invoke('execute', { + await vanillaAuthenticator.invoke('authenticate', { target: spaceAddress, - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata1, }); } @@ -105,9 +103,9 @@ describe('Whitelist testing', () => { it('Should not be able to create a proposal with a non whitelisted executor', async () => { try { // proposeCalldata2 contains the vanilla execution strategy which is not whitelisted initially - await vanillaAuthenticator.invoke('execute', { + await vanillaAuthenticator.invoke('authenticate', { target: spaceAddress, - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata2, }); } catch (err: any) { @@ -120,9 +118,9 @@ describe('Whitelist testing', () => { to_add: [BigInt(vanillaExecutionStrategy.address)], }); - await vanillaAuthenticator.invoke('execute', { + await vanillaAuthenticator.invoke('authenticate', { target: spaceAddress, - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata2, }); }).timeout(1000000); @@ -134,9 +132,9 @@ describe('Whitelist testing', () => { try { // Try to create a proposal, should fail because it just got removed from the whitelist - await vanillaAuthenticator.invoke('execute', { + await vanillaAuthenticator.invoke('authenticate', { target: spaceAddress, - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata1, }); } catch (err: any) { @@ -149,9 +147,9 @@ describe('Whitelist testing', () => { to_add: [BigInt(zodiacRelayer.address), BigInt(vanillaExecutionStrategy.address)], }); - await vanillaAuthenticator.invoke('execute', { + await vanillaAuthenticator.invoke('authenticate', { target: spaceAddress, - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata2, }); }).timeout(1000000); diff --git a/test/starknet/Space.test.ts b/test/starknet/Space.test.ts index ed113904..22f2f960 100644 --- a/test/starknet/Space.test.ts +++ b/test/starknet/Space.test.ts @@ -1,13 +1,11 @@ import { expect } from 'chai'; import { ethers } from 'hardhat'; -import { stark } from 'starknet'; import { StarknetContract, Account } from 'hardhat/types'; import { strToShortStringArr } from '@snapshot-labs/sx'; import { SplitUint256, Choice } from '../shared/types'; import { getProposeCalldata, getVoteCalldata, bytesToHex } from '../shared/helpers'; import { vanillaSetup } from '../shared/setup'; - -const { getSelectorFromName } = stark; +import { PROPOSE_SELECTOR, VOTE_SELECTOR } from '../shared/constants'; describe('Space Testing', () => { // Contracts @@ -79,12 +77,12 @@ describe('Space Testing', () => { ); }); - it('Users should be able to create a proposal, cast a vote, and execute', async () => { + it('Users should be able to create a proposal, cast a vote, and execute it', async () => { // -- Creates the proposal -- { - await vanillaAuthenticator.invoke('execute', { + await vanillaAuthenticator.invoke('authenticate', { target: spaceAddress, - function_selector: BigInt(getSelectorFromName('propose')), + function_selector: PROPOSE_SELECTOR, calldata: proposeCalldata, }); @@ -103,9 +101,9 @@ describe('Space Testing', () => { } // -- Casts a vote FOR -- { - await vanillaAuthenticator.invoke('execute', { + await vanillaAuthenticator.invoke('authenticate', { target: spaceAddress, - function_selector: BigInt(getSelectorFromName('vote')), + function_selector: VOTE_SELECTOR, calldata: voteCalldata, }); diff --git a/test/starknet/StarkTxAuth.test.ts b/test/starknet/StarkTxAuth.test.ts index 50375ff3..c4e87ce5 100644 --- a/test/starknet/StarkTxAuth.test.ts +++ b/test/starknet/StarkTxAuth.test.ts @@ -1,75 +1,100 @@ -import { stark } from 'starknet'; -import { SplitUint256, Choice } from '../shared/types'; -import { flatten2DArray } from '../shared/helpers'; -import { strToShortStringArr } from '@snapshot-labs/sx'; import { expect } from 'chai'; -import { starknetTxSetup } from '../shared/setup'; +import { starknet, ethers } from 'hardhat'; import { StarknetContract, Account } from 'hardhat/types'; +import { strToShortStringArr } from '@snapshot-labs/sx'; +import { SplitUint256, Choice } from '../shared/types'; +import { getProposeCalldata, getVoteCalldata, bytesToHex } from '../shared/helpers'; +import { starkTxAuthSetup } from '../shared/setup'; +import { PROPOSE_SELECTOR, VOTE_SELECTOR } from '../shared/constants'; -const { getSelectorFromName } = stark; - -export const VITALIK_ADDRESS = BigInt('0xd8da6bf26964af9d7eed9e03e53415d37aa96045'); -export const AUTHENTICATE_METHOD = 'authenticate'; -export const PROPOSAL_METHOD = 'propose'; -export const VOTE_METHOD = 'vote'; +const VITALIK_ADDRESS = BigInt('0xd8da6bf26964af9d7eed9e03e53415d37aa96045'); -describe('Starknet Tx Auth testing', () => { - let vanillaSpace: StarknetContract; - let starknetTxAuth: StarknetContract; +describe('StarkNet Tx Auth testing', () => { + // Contracts + let space: StarknetContract; + let controller: Account; + let starknetTxAuthenticator: StarknetContract; let vanillaVotingStrategy: StarknetContract; - let zodiacRelayer: StarknetContract; - const executionHash = new SplitUint256(BigInt(1), BigInt(2)); // Dummy uint256 - const metadataUri = strToShortStringArr( - 'Hello and welcome to Snapshot X. This is the future of governance.' - ); - let proposerAddress: bigint; - const proposalId = 1; - const votingParamsAll: bigint[][] = [[]]; - const votingParamsAllFlat = flatten2DArray(votingParamsAll); - let used_voting_strategies: Array; - let executionParams: Array; - const ethBlockNumber = BigInt(1337); - const l1_zodiac_module = BigInt('0xaaaaaaaaaaaa'); - let calldata: Array; - let spaceContract: bigint; - let account: Account; + let vanillaExecutionStrategy: StarknetContract; + + // Proposal creation parameters + let spaceAddress: bigint; + let executionHash: string; + let metadataUri: bigint[]; + let proposerAccount: Account; + let proposerAddress: string; + let usedVotingStrategies1: bigint[]; + let userVotingParamsAll1: bigint[][]; + let executionStrategy: bigint; + let executionParams: bigint[]; + let ethBlockNumber: bigint; + let proposeCalldata: bigint[]; + + // Additional parameters for voting + let voterAccount: Account; + let voterAddress: string; + let proposalId: bigint; + let choice: Choice; + let usedVotingStrategies2: bigint[]; + let userVotingParamsAll2: bigint[][]; + let voteCalldata: bigint[]; before(async function () { this.timeout(800000); + proposerAccount = (await starknet.deployAccount('OpenZeppelin')) as Account; + voterAccount = (await starknet.deployAccount('OpenZeppelin')) as Account; + ({ + space, + controller, + starknetTxAuthenticator, + vanillaVotingStrategy, + vanillaExecutionStrategy, + } = await starkTxAuthSetup()); - ({ vanillaSpace, starknetTxAuth, vanillaVotingStrategy, zodiacRelayer, account } = - await starknetTxSetup()); - executionParams = [BigInt(l1_zodiac_module)]; - spaceContract = BigInt(vanillaSpace.address); - used_voting_strategies = [BigInt(vanillaVotingStrategy.address)]; - proposerAddress = BigInt(account.starknetContract.address); - - calldata = [ + executionHash = bytesToHex(ethers.utils.randomBytes(32)); // Random 32 byte hash + metadataUri = strToShortStringArr( + 'Hello and welcome to Snapshot X. This is the future of governance.' + ); + proposerAddress = proposerAccount.starknetContract.address; + ethBlockNumber = BigInt(1337); + spaceAddress = BigInt(space.address); + usedVotingStrategies1 = [BigInt(vanillaVotingStrategy.address)]; + userVotingParamsAll1 = [[]]; + executionStrategy = BigInt(vanillaExecutionStrategy.address); + executionParams = []; + proposeCalldata = getProposeCalldata( proposerAddress, - executionHash.low, - executionHash.high, - BigInt(metadataUri.length), - ...metadataUri, + executionHash, + metadataUri, ethBlockNumber, - BigInt(zodiacRelayer.address), - BigInt(used_voting_strategies.length), - ...used_voting_strategies, - BigInt(votingParamsAllFlat.length), - ...votingParamsAllFlat, - BigInt(executionParams.length), - ...executionParams, - ]; + executionStrategy, + usedVotingStrategies1, + userVotingParamsAll1, + executionParams + ); + + voterAddress = voterAccount.starknetContract.address; + proposalId = BigInt(1); + choice = Choice.FOR; + usedVotingStrategies2 = [BigInt(vanillaVotingStrategy.address)]; + userVotingParamsAll2 = [[]]; + voteCalldata = getVoteCalldata( + voterAddress, + proposalId, + choice, + usedVotingStrategies2, + userVotingParamsAll2 + ); }); it('Should not authenticate an invalid user', async () => { + const fakeData = [...proposeCalldata]; + fakeData[0] = VITALIK_ADDRESS; try { - const fake_data = [...calldata]; - fake_data[0] = VITALIK_ADDRESS; - - await account.invoke(starknetTxAuth, AUTHENTICATE_METHOD, { - target: spaceContract, - function_selector: BigInt(getSelectorFromName(PROPOSAL_METHOD)), - calldata: fake_data, + await proposerAccount.invoke(starknetTxAuthenticator, 'authenticate', { + target: spaceAddress, + function_selector: PROPOSE_SELECTOR, + calldata: fakeData, }); throw 'error'; } catch (err: any) { @@ -81,21 +106,19 @@ describe('Starknet Tx Auth testing', () => { // -- Creates the proposal -- { console.log('Creating proposal...'); - await account.invoke(starknetTxAuth, AUTHENTICATE_METHOD, { - target: spaceContract, - function_selector: BigInt(getSelectorFromName(PROPOSAL_METHOD)), - calldata, + await proposerAccount.invoke(starknetTxAuthenticator, 'authenticate', { + target: spaceAddress, + function_selector: PROPOSE_SELECTOR, + calldata: proposeCalldata, }); console.log('Getting proposal info...'); - const { proposal_info } = await vanillaSpace.call('get_proposal_info', { + const { proposal_info } = await space.call('get_proposal_info', { proposal_id: proposalId, }); - // We can't directly compare the `info` object because we don't know for sure the value of `start_block` (and hence `end_block`), - // so we compare it element by element. - const _executionHash = SplitUint256.fromObj(proposal_info.proposal.execution_hash); - expect(_executionHash).to.deep.equal(executionHash); + const _executionHash = SplitUint256.fromObj(proposal_info.proposal.execution_hash).toUint(); + expect(_executionHash).to.deep.equal(BigInt(executionHash)); const _for = SplitUint256.fromObj(proposal_info.power_for).toUint(); expect(_for).to.deep.equal(BigInt(0)); @@ -108,25 +131,14 @@ describe('Starknet Tx Auth testing', () => { // -- Casts a vote FOR -- { console.log('Casting a vote FOR...'); - const voter_address = proposerAddress; - const votingparams: Array = []; - const used_voting_strategies = [BigInt(vanillaVotingStrategy.address)]; - await account.invoke(starknetTxAuth, AUTHENTICATE_METHOD, { - target: spaceContract, - function_selector: BigInt(getSelectorFromName(VOTE_METHOD)), - calldata: [ - voter_address, - proposalId, - Choice.FOR, - BigInt(used_voting_strategies.length), - ...used_voting_strategies, - BigInt(votingParamsAllFlat.length), - ...votingParamsAllFlat, - ], + await voterAccount.invoke(starknetTxAuthenticator, 'authenticate', { + target: spaceAddress, + function_selector: VOTE_SELECTOR, + calldata: voteCalldata, }); console.log('Getting proposal info...'); - const { proposal_info } = await vanillaSpace.call('get_proposal_info', { + const { proposal_info } = await space.call('get_proposal_info', { proposal_id: proposalId, }); diff --git a/tsconfig.json b/tsconfig.json index 86b78bf7..10c33d9e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,17 @@ { - "compilerOptions": { - "target": "es5", - "module": "commonjs", - "strict": true, - "esModuleInterop": true, - "outDir": "dist", - "resolveJsonModule": true - }, - "include": ["./scripts", "./test"], - "files": ["./hardhat.config.ts"] -} + "compilerOptions": { + "esModuleInterop": true, + "module": "commonjs", + "outDir": "dist", + "resolveJsonModule": true, + "strict": true, + "target": "es5" + }, + "files": [ + "./hardhat.config.ts" + ], + "include": [ + "./scripts", + "./test" + ] +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index acf4ca3e..4b2e3c47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6267,6 +6267,14 @@ json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" +json-format-cli@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/json-format-cli/-/json-format-cli-1.1.1.tgz#1c25ddc55e786c2886a808dd39e4fbed03aade95" + integrity sha512-IMQ+/RZkxVVSBxPB8EdwD7gipqQtuPYGumWHryyoc9Q7rhcOi+O9dlZaInlMpwjv4rdFoTEU09hkVBgrmeh6Ew== + dependencies: + json-stable-stringify "^1.0.1" + minimist "^1.2.0" + json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -8230,6 +8238,14 @@ pretty-format@^27.0.0, pretty-format@^27.5.1: ansi-styles "^5.0.0" react-is "^17.0.1" +prettyjson@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-1.2.5.tgz#ef3cfffcc70505c032abc59785884b4027031835" + integrity sha512-rksPWtoZb2ZpT5OVgtmy0KHVM+Dca3iVwWY9ifwhcexfjebtgjg3wmrUt9PvJ59XIYBcknQeYHD8IAnVlh9lAw== + dependencies: + colors "1.4.0" + minimist "^1.2.0" + private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -9439,22 +9455,7 @@ stacktrace-parser@^0.1.10: dependencies: type-fest "^0.7.1" -starknet@^2.5.1: - version "2.9.0" - resolved "https://registry.yarnpkg.com/starknet/-/starknet-2.9.0.tgz#a263e603a45441785991f2c18fcecd8722d6368b" - dependencies: - axios "^0.23.0" - bn.js "^5.2.0" - elliptic "^6.5.4" - ethereum-cryptography "^0.2.0" - hash.js "^1.1.7" - json-bigint "^1.0.0" - minimalistic-assert "^1.0.1" - pako "^2.0.4" - superstruct "^0.15.3" - url-join "^4.0.1" - -starknet@^3.2.0, starknet@^3.5.1, starknet@^3.7.0: +starknet@^3.2.0, starknet@^3.5.1, starknet@^3.7.0, starknet@^3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/starknet/-/starknet-3.9.0.tgz#ee7a3d99effef0998b365d95dd85f9b01cdb463c" dependencies: