-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add factory and upgrade method (#462)
* feat: add factory * feat: upgrade method and tests * fix: remove useless setup in constructor test * fix: set caller address and contract address * refactor: rename executioner to executor * chore: remove useless comment * chore: remove dead code * typo: execution instead of exection * comment: execution strategy instead of space itself * refactor: move StrategyImpl to tests folder
- Loading branch information
Showing
14 changed files
with
561 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
mod factory; | ||
use factory::Factory; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
use starknet::ContractAddress; | ||
use starknet::ClassHash; | ||
|
||
#[starknet::interface] | ||
trait IFactory<TContractState> { | ||
fn deploy( | ||
self: @TContractState, | ||
class_hash: ClassHash, | ||
contract_address_salt: felt252, | ||
calldata: Span<felt252> | ||
) -> ContractAddress; | ||
} | ||
|
||
|
||
#[starknet::contract] | ||
mod Factory { | ||
use super::IFactory; | ||
use starknet::ContractAddress; | ||
use starknet::contract_address_const; | ||
use starknet::syscalls::deploy_syscall; | ||
use starknet::ClassHash; | ||
use result::ResultTrait; | ||
|
||
#[event] | ||
fn SpaceDeployed(class_hash: ClassHash, space_address: ContractAddress) {} | ||
|
||
#[storage] | ||
struct Storage {} | ||
|
||
#[external(v0)] | ||
impl Factory of IFactory<ContractState> { | ||
fn deploy( | ||
self: @ContractState, | ||
class_hash: ClassHash, | ||
contract_address_salt: felt252, | ||
calldata: Span<felt252> | ||
) -> ContractAddress { | ||
let (space_address, _) = deploy_syscall( | ||
class_hash, contract_address_salt, calldata, false | ||
) | ||
.unwrap(); | ||
|
||
SpaceDeployed(class_hash, space_address); | ||
|
||
space_address | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
mod space; | ||
|
||
mod factory; | ||
|
||
mod proposal_validation_strategies; | ||
|
||
mod authenticators; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
mod test_space; | ||
mod test_factory; | ||
mod test_upgrade; | ||
|
||
mod mocks; | ||
mod setup; | ||
|
||
mod utils; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
mod proposal_validation_always_fail; | ||
mod executor; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#[starknet::contract] | ||
mod ExecutorExecutionStrategy { | ||
use sx::interfaces::IExecutionStrategy; | ||
use sx::utils::types::{Proposal, ProposalStatus}; | ||
use sx::execution_strategies::simple_quorum::SimpleQuorumExecutionStrategy; | ||
use starknet::ContractAddress; | ||
use core::serde::Serde; | ||
use core::array::ArrayTrait; | ||
use option::OptionTrait; | ||
use starknet::syscalls::call_contract_syscall; | ||
|
||
#[storage] | ||
struct Storage {} | ||
|
||
#[derive(Drop, Serde)] | ||
struct Transaction { | ||
target: ContractAddress, | ||
selector: felt252, | ||
data: Array<felt252>, | ||
} | ||
|
||
#[external(v0)] | ||
impl ExecutorExecutionStrategy of IExecutionStrategy<ContractState> { | ||
// Dummy function that will just execute the `Transaction` in the payload, without needing any quorum. | ||
fn execute( | ||
ref self: ContractState, | ||
proposal: Proposal, | ||
votes_for: u256, | ||
votes_against: u256, | ||
votes_abstain: u256, | ||
payload: Array<felt252> | ||
) { | ||
let mut sp4n = payload.span(); | ||
let tx: Transaction = Serde::<Transaction>::deserialize(ref sp4n).unwrap(); | ||
call_contract_syscall(tx.target, tx.selector, tx.data.span()).unwrap_syscall(); | ||
} | ||
} | ||
|
||
#[constructor] | ||
fn constructor(ref self: ContractState) {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mod setup; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
#[cfg(test)] | ||
mod setup { | ||
use array::ArrayTrait; | ||
use starknet::{ContractAddress, contract_address_const}; | ||
use traits::{Into, TryInto}; | ||
use serde::{Serde}; | ||
use result::ResultTrait; | ||
use option::OptionTrait; | ||
use sx::utils::types::Strategy; | ||
use sx::authenticators::vanilla::{VanillaAuthenticator}; | ||
use sx::execution_strategies::vanilla::VanillaExecutionStrategy; | ||
use sx::voting_strategies::vanilla::VanillaVotingStrategy; | ||
use sx::proposal_validation_strategies::vanilla::VanillaProposalValidationStrategy; | ||
use sx::tests::utils::strategy_trait::StrategyImpl; | ||
use integer::u256_from_felt252; | ||
use starknet::testing; | ||
use starknet::syscalls::deploy_syscall; | ||
use sx::factory::factory::{Factory, IFactoryDispatcher, IFactoryDispatcherTrait}; | ||
use starknet::ClassHash; | ||
use sx::space::space::{Space, ISpaceDispatcher, ISpaceDispatcherTrait}; | ||
|
||
#[derive(Drop)] | ||
struct Config { | ||
owner: ContractAddress, | ||
min_voting_duration: u64, | ||
max_voting_duration: u64, | ||
voting_delay: u64, | ||
proposal_validation_strategy: Strategy, | ||
voting_strategies: Array<Strategy>, | ||
authenticators: Array<ContractAddress>, | ||
} | ||
|
||
fn setup() -> Config { | ||
let deployer = contract_address_const::<0x1234>(); | ||
testing::set_caller_address(deployer); | ||
testing::set_contract_address(deployer); | ||
|
||
// Space Settings | ||
let owner = contract_address_const::<0x123456789>(); | ||
let max_voting_duration = 2_u64; | ||
let min_voting_duration = 1_u64; | ||
let voting_delay = 1_u64; | ||
let quorum = u256_from_felt252(1); | ||
|
||
// Deploy Vanilla Authenticator | ||
let (vanilla_authenticator_address, _) = deploy_syscall( | ||
VanillaAuthenticator::TEST_CLASS_HASH.try_into().unwrap(), | ||
0, | ||
array::ArrayTrait::<felt252>::new().span(), | ||
false | ||
) | ||
.unwrap(); | ||
let mut authenticators = ArrayTrait::<ContractAddress>::new(); | ||
authenticators.append(vanilla_authenticator_address); | ||
|
||
// Deploy Vanilla Proposal Validation Strategy | ||
let (vanilla_proposal_validation_address, _) = deploy_syscall( | ||
VanillaProposalValidationStrategy::TEST_CLASS_HASH.try_into().unwrap(), | ||
0, | ||
array::ArrayTrait::<felt252>::new().span(), | ||
false | ||
) | ||
.unwrap(); | ||
let proposal_validation_strategy = StrategyImpl::from_address( | ||
vanilla_proposal_validation_address | ||
); | ||
|
||
// Deploy Vanilla Voting Strategy | ||
let (vanilla_voting_strategy_address, _) = deploy_syscall( | ||
VanillaVotingStrategy::TEST_CLASS_HASH.try_into().unwrap(), | ||
0, | ||
array::ArrayTrait::<felt252>::new().span(), | ||
false | ||
) | ||
.unwrap(); | ||
let mut voting_strategies = ArrayTrait::<Strategy>::new(); | ||
voting_strategies | ||
.append( | ||
Strategy { | ||
address: vanilla_voting_strategy_address, params: ArrayTrait::<felt252>::new() | ||
} | ||
); | ||
|
||
// Deploy Vanilla Execution Strategy | ||
let mut constructor_calldata = ArrayTrait::<felt252>::new(); | ||
quorum.serialize(ref constructor_calldata); | ||
let (vanilla_execution_strategy_address, _) = deploy_syscall( | ||
VanillaExecutionStrategy::TEST_CLASS_HASH.try_into().unwrap(), | ||
0, | ||
constructor_calldata.span(), | ||
false | ||
) | ||
.unwrap(); | ||
let vanilla_execution_strategy = StrategyImpl::from_address( | ||
vanilla_execution_strategy_address | ||
); | ||
|
||
Config { | ||
owner, | ||
min_voting_duration, | ||
max_voting_duration, | ||
voting_delay, | ||
proposal_validation_strategy, | ||
voting_strategies, | ||
authenticators | ||
} | ||
} | ||
|
||
fn get_constructor_calldata( | ||
owner: @ContractAddress, | ||
min_voting_duration: @u64, | ||
max_voting_duration: @u64, | ||
voting_delay: @u64, | ||
proposal_validation_strategy: @Strategy, | ||
voting_strategies: @Array<Strategy>, | ||
authenticators: @Array<ContractAddress> | ||
) -> Array<felt252> { | ||
let mut constructor_calldata = array::ArrayTrait::<felt252>::new(); | ||
constructor_calldata.append((*owner).into()); | ||
constructor_calldata.append((*max_voting_duration).into()); | ||
constructor_calldata.append((*min_voting_duration).into()); | ||
constructor_calldata.append((*voting_delay).into()); | ||
proposal_validation_strategy.serialize(ref constructor_calldata); | ||
voting_strategies.serialize(ref constructor_calldata); | ||
authenticators.serialize(ref constructor_calldata); | ||
|
||
constructor_calldata | ||
} | ||
|
||
fn deploy(config: @Config) -> (IFactoryDispatcher, ISpaceDispatcher) { | ||
let space_class_hash: ClassHash = Space::TEST_CLASS_HASH.try_into().unwrap(); | ||
let contract_address_salt = 0; | ||
|
||
let (factory_address, _) = deploy_syscall( | ||
Factory::TEST_CLASS_HASH.try_into().unwrap(), | ||
0, | ||
ArrayTrait::<felt252>::new().span(), | ||
false | ||
) | ||
.unwrap(); | ||
|
||
let factory = IFactoryDispatcher { contract_address: factory_address }; | ||
|
||
let constructor_calldata = get_constructor_calldata( | ||
config.owner, | ||
config.min_voting_duration, | ||
config.max_voting_duration, | ||
config.voting_delay, | ||
config.proposal_validation_strategy, | ||
config.voting_strategies, | ||
config.authenticators | ||
); | ||
let space_address = factory | ||
.deploy(space_class_hash, contract_address_salt, constructor_calldata.span()); | ||
|
||
let space = ISpaceDispatcher { contract_address: space_address }; | ||
|
||
(factory, space) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#[cfg(test)] | ||
mod tests { | ||
use array::ArrayTrait; | ||
use starknet::{syscalls::deploy_syscall, testing, contract_address_const, }; | ||
use traits::TryInto; | ||
use sx::factory::factory::{Factory, IFactoryDispatcher, IFactoryDispatcherTrait}; | ||
use option::OptionTrait; | ||
use result::ResultTrait; | ||
use sx::space::space::Space; | ||
use sx::utils::types::Strategy; | ||
use starknet::ClassHash; | ||
|
||
use sx::tests::setup::setup::setup::{setup, get_constructor_calldata, deploy}; | ||
|
||
#[test] | ||
#[available_gas(10000000000)] | ||
fn test_deploy() { | ||
// Deploy Space | ||
let config = setup(); | ||
|
||
// TODO: check event gets emitted | ||
deploy(@config); | ||
} | ||
|
||
|
||
#[test] | ||
#[available_gas(10000000000)] | ||
fn test_deploy_reuse_salt() { | ||
let mut constructor_calldata = ArrayTrait::<felt252>::new(); | ||
|
||
let (factory_address, _) = deploy_syscall( | ||
Factory::TEST_CLASS_HASH.try_into().unwrap(), 0, constructor_calldata.span(), false | ||
) | ||
.unwrap(); | ||
|
||
let factory = IFactoryDispatcher { contract_address: factory_address }; | ||
|
||
let space_class_hash: ClassHash = Space::TEST_CLASS_HASH.try_into().unwrap(); | ||
let contract_address_salt = 0; | ||
|
||
let config = setup(); | ||
let constructor_calldata = get_constructor_calldata( | ||
@config.owner, | ||
@config.min_voting_duration, | ||
@config.max_voting_duration, | ||
@config.voting_delay, | ||
@config.proposal_validation_strategy, | ||
@config.voting_strategies, | ||
@config.authenticators | ||
); | ||
|
||
let space_address = factory | ||
.deploy(space_class_hash, contract_address_salt, constructor_calldata.span()); | ||
let space_address_2 = factory | ||
.deploy(space_class_hash, contract_address_salt, constructor_calldata.span()); | ||
// TODO: this test should fail but doesn't fail currently because of how the test environment works | ||
} | ||
} |
Oops, something went wrong.