Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce internal components #634

Merged
merged 14 commits into from
Oct 21, 2024
24 changes: 5 additions & 19 deletions starknet/src/authenticators/eth_sig.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ mod EthSigAuthenticator {
use starknet::{ContractAddress, EthAddress};
use sx::interfaces::{ISpaceDispatcher, ISpaceDispatcherTrait};
use sx::types::{Strategy, IndexedStrategy, Choice, UserAddress};
use sx::utils::{EIP712, LegacyHashEthAddress, ByteReverse};
use sx::utils::{eip712, LegacyHashEthAddress, ByteReverse};

#[storage]
struct Storage {
Expand All @@ -112,9 +112,7 @@ mod EthSigAuthenticator {
) {
assert(!self._used_salts.read((author, salt)), 'Salt Already Used');

let state = EIP712::unsafe_new_contract_state();
EIP712::InternalImpl::verify_propose_sig(
@state,
eip712::verify_propose_sig(
r,
s,
v,
Expand Down Expand Up @@ -149,9 +147,7 @@ mod EthSigAuthenticator {
) {
// No need to check salts here, as double voting is prevented by the space itself.

let state = EIP712::unsafe_new_contract_state();
EIP712::InternalImpl::verify_vote_sig(
@state,
eip712::verify_vote_sig(
r,
s,
v,
Expand Down Expand Up @@ -187,18 +183,8 @@ mod EthSigAuthenticator {
) {
assert(!self._used_salts.read((author, salt)), 'Salt Already Used');

let state = EIP712::unsafe_new_contract_state();
EIP712::InternalImpl::verify_update_proposal_sig(
@state,
r,
s,
v,
space,
author,
proposal_id,
@execution_strategy,
metadata_uri.span(),
salt
eip712::verify_update_proposal_sig(
r, s, v, space, author, proposal_id, @execution_strategy, metadata_uri.span(), salt
);
self._used_salts.write((author, salt), true);
ISpaceDispatcher { contract_address: space }
Expand Down
85 changes: 48 additions & 37 deletions starknet/src/authenticators/stark_sig.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,23 @@ mod StarkSigAuthenticator {
use starknet::{ContractAddress, info};
use sx::interfaces::{ISpaceDispatcher, ISpaceDispatcherTrait};
use sx::types::{Strategy, IndexedStrategy, UserAddress, Choice};
use sx::utils::SNIP12;
use sx::utils::snip12::SNIP12Component;

component!(path: SNIP12Component, storage: snip12, event: SNIP12Event);

impl SNIP12InternalImpl = SNIP12Component::InternalImpl<ContractState>;

#[storage]
struct Storage {
_used_salts: LegacyMap::<(ContractAddress, felt252), bool>
_used_salts: LegacyMap::<(ContractAddress, felt252), bool>,
#[substorage(v0)]
snip12: SNIP12Component::Storage
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
SNIP12Event: SNIP12Component::Event
}

#[abi(embed_v0)]
Expand All @@ -102,17 +114,17 @@ mod StarkSigAuthenticator {
) {
assert(!self._used_salts.read((author, salt)), 'Salt Already Used');

let state = SNIP12::unsafe_new_contract_state();
SNIP12::InternalImpl::verify_propose_sig(
@state,
signature,
space,
author,
metadata_uri.span(),
@execution_strategy,
user_proposal_validation_params.span(),
salt
);
self
.snip12
.verify_propose_sig(
signature,
space,
author,
metadata_uri.span(),
@execution_strategy,
user_proposal_validation_params.span(),
salt
);

self._used_salts.write((author, salt), true);
ISpaceDispatcher { contract_address: space }
Expand All @@ -136,17 +148,17 @@ mod StarkSigAuthenticator {
) {
// No need to check salts here, as double voting is prevented by the space itself.

let state = SNIP12::unsafe_new_contract_state();
SNIP12::InternalImpl::verify_vote_sig(
@state,
signature,
space,
voter,
proposal_id,
choice,
user_voting_strategies.span(),
metadata_uri.span()
);
self
.snip12
.verify_vote_sig(
signature,
space,
voter,
proposal_id,
choice,
user_voting_strategies.span(),
metadata_uri.span()
);

ISpaceDispatcher { contract_address: space }
.vote(
Expand All @@ -170,17 +182,17 @@ mod StarkSigAuthenticator {
) {
assert(!self._used_salts.read((author, salt)), 'Salt Already Used');

let state = SNIP12::unsafe_new_contract_state();
SNIP12::InternalImpl::verify_update_proposal_sig(
@state,
signature,
space,
author,
proposal_id,
@execution_strategy,
metadata_uri.span(),
salt
);
self
.snip12
.verify_update_proposal_sig(
signature,
space,
author,
proposal_id,
@execution_strategy,
metadata_uri.span(),
salt
);

self._used_salts.write((author, salt), true);
ISpaceDispatcher { contract_address: space }
Expand All @@ -191,7 +203,6 @@ mod StarkSigAuthenticator {
}
#[constructor]
fn constructor(ref self: ContractState, name: felt252, version: felt252) {
let mut state = SNIP12::unsafe_new_contract_state();
SNIP12::InternalImpl::initializer(ref state, name, version);
self.snip12.initializer(name, version);
}
}
82 changes: 34 additions & 48 deletions starknet/src/execution_strategies/timelock.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@ trait ITimelockExecutionStrategy<TContractState> {
fn disable_space(ref self: TContractState, space: ContractAddress);

fn is_space_enabled(self: @TContractState, space: ContractAddress) -> bool;

/// Transfers the ownership to `new_owner`.
fn transfer_ownership(ref self: TContractState, new_owner: ContractAddress);
/// Renounces the ownership of the contract. CAUTION: This is a one-way operation.
fn renounce_ownership(ref self: TContractState);

fn owner(self: @TContractState) -> ContractAddress;
}

#[starknet::contract]
Expand All @@ -37,20 +30,34 @@ mod TimelockExecutionStrategy {
use sx::interfaces::IExecutionStrategy;
use super::ITimelockExecutionStrategy;
use sx::types::{Proposal, ProposalStatus};
use sx::utils::{SimpleQuorum, SpaceManager};
use sx::utils::{simple_quorum::SimpleQuorumComponent, space_manager::SpaceManagerComponent};

component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);

impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;
#[abi(embed_v0)]
impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;

component!(path: SimpleQuorumComponent, storage: simple_quorum, event: SimpleQuorumEvent);

#[abi(embed_v0)]
impl SimpleQuorumImpl = SimpleQuorumComponent::SimpleQuorumImpl<ContractState>;
impl SimpleQuorumInternalImpl = SimpleQuorumComponent::InternalImpl<ContractState>;

component!(path: SpaceManagerComponent, storage: space_manager, event: SpaceManagerEvent);
impl SpaceManagerInternalImpl = SpaceManagerComponent::InternalImpl<ContractState>;

#[storage]
struct Storage {
_timelock_delay: u32,
_veto_guardian: ContractAddress,
_proposal_execution_time: LegacyMap::<felt252, u32>,
#[substorage(v0)]
ownable: OwnableComponent::Storage
ownable: OwnableComponent::Storage,
#[substorage(v0)]
simple_quorum: SimpleQuorumComponent::Storage,
#[substorage(v0)]
space_manager: SpaceManagerComponent::Storage,
}

#[event]
Expand All @@ -65,7 +72,11 @@ mod TimelockExecutionStrategy {
ProposalExecuted: ProposalExecuted,
ProposalVetoed: ProposalVetoed,
#[flat]
OwnableEvent: OwnableComponent::Event
OwnableEvent: OwnableComponent::Event,
#[flat]
SimpleQuorumEvent: SimpleQuorumComponent::Event,
#[flat]
SpaceManagerEvent: SpaceManagerComponent::Event,
}

#[derive(Drop, PartialEq, starknet::Event)]
Expand Down Expand Up @@ -132,11 +143,9 @@ mod TimelockExecutionStrategy {
) {
self.ownable.initializer(owner);

let mut state = SimpleQuorum::unsafe_new_contract_state();
SimpleQuorum::InternalImpl::initializer(ref state, quorum);
self.simple_quorum.initializer(quorum);

let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::initializer(ref state, spaces);
self.space_manager.initializer(spaces);

self._timelock_delay.write(timelock_delay);
self._veto_guardian.write(veto_guardian);
Expand All @@ -153,14 +162,10 @@ mod TimelockExecutionStrategy {
votes_abstain: u256,
payload: Array<felt252>
) {
// Migration to components planned ; disregard the `unsafe` keyword,
// it is actually safe.
let state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::assert_only_spaces(@state);
let state = SimpleQuorum::unsafe_new_contract_state();
let proposal_status = SimpleQuorum::InternalImpl::get_proposal_status(
@state, @proposal, votes_for, votes_against, votes_abstain
);
self.space_manager.assert_only_spaces();
let proposal_status = self
.simple_quorum
.get_proposal_status(@proposal, votes_for, votes_against, votes_abstain);
assert(
proposal_status == ProposalStatus::Accepted(())
|| proposal_status == ProposalStatus::VotingPeriodAccepted(()),
Expand Down Expand Up @@ -201,10 +206,9 @@ mod TimelockExecutionStrategy {
votes_against: u256,
votes_abstain: u256,
) -> ProposalStatus {
let state = SimpleQuorum::unsafe_new_contract_state();
SimpleQuorum::InternalImpl::get_proposal_status(
@state, @proposal, votes_for, votes_against, votes_abstain
)
self
.simple_quorum
.get_proposal_status(@proposal, votes_for, votes_against, votes_abstain)
}

fn get_strategy_type(self: @ContractState) -> felt252 {
Expand Down Expand Up @@ -295,34 +299,16 @@ mod TimelockExecutionStrategy {

fn enable_space(ref self: ContractState, space: ContractAddress) {
self.ownable.assert_only_owner();
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::enable_space(ref state, space);
self.space_manager.enable_space(space);
}

fn disable_space(ref self: ContractState, space: ContractAddress) {
self.ownable.assert_only_owner();
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::disable_space(ref state, space);
self.space_manager.disable_space(space);
}

fn is_space_enabled(self: @ContractState, space: ContractAddress) -> bool {
// Migration to components planned ; disregard the `unsafe` keyword,
// it is actually safe.
let state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::is_space_enabled(@state, space)
}

// TODO: use Ownable impl as abi_embed(v0)?
fn owner(self: @ContractState) -> ContractAddress {
self.ownable.owner()
}

fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) {
self.ownable.transfer_ownership(new_owner);
}

fn renounce_ownership(ref self: ContractState) {
self.ownable.renounce_ownership();
self.space_manager.is_space_enabled(space)
}
}

Expand Down
28 changes: 28 additions & 0 deletions starknet/src/interfaces/i_single_slot_proof.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use sx::external::herodotus::BinarySearchTree;

/// Optional trait that execution strategies can decide to implement.
#[starknet::interface]
trait ISingleSlotProof<TContractState> {
/// Queries the Timestamp Remapper contract for the closest L1 block number that occurred before
/// the given timestamp and then caches the result. If the queried timestamp is less than the earliest
/// timestamp or larger than the latest timestamp in the mapper then the transaction will revert.
/// This function should be used to cache a remapped timestamp before it's used when calling the
/// `get_storage_slot` function with the same timestamp.
///
/// # Arguments
///
/// * `timestamp` - The timestamp at which to query.
/// * `tree` - The tree proof required to query the remapper.
fn cache_timestamp(ref self: TContractState, timestamp: u32, tree: BinarySearchTree);

/// View function exposing the cached remapped timestamps. Reverts if the timestamp is not cached.
///
/// # Arguments
///
/// * `timestamp` - The timestamp to query.
///
/// # Returns
///
/// * `u256` - The cached L1 block number corresponding to the timestamp.
fn cached_timestamps(self: @TContractState, timestamp: u32) -> u256;
}
7 changes: 0 additions & 7 deletions starknet/src/interfaces/i_space.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ use sx::types::{
trait ISpace<TContractState> {
// -- View functions --

/// Returns the owner of the contract.
fn owner(self: @TContractState) -> ContractAddress;

/// The voting delay in seconds between when a proposal is created and the start of the voting period.
fn voting_delay(self: @TContractState) -> u32;

Expand Down Expand Up @@ -60,10 +57,6 @@ trait ISpace<TContractState> {
/// struct is passed to be able to update different settings in a single call. Settings that should not
/// be updated should have the `no_update` value (see `UpdateSettingsCalldata`).
fn update_settings(ref self: TContractState, input: UpdateSettingsCalldata);
/// Transfers the ownership to `new_owner`.
fn transfer_ownership(ref self: TContractState, new_owner: ContractAddress);
/// Renounces the ownership of the contract. CAUTION: This is a one-way operation.
fn renounce_ownership(ref self: TContractState);

// -- Actions --
/// Initializes the contract. Can only be called once.
Expand Down
Loading
Loading