From 965c418db297d6671a9ed97e9e32dfc20466933e Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 11 Nov 2024 18:10:43 +0530 Subject: [PATCH 1/8] [FEAT] added support for L2 starknet token and multisig[IN_PROGRESS] --- cairo/.gitignore | 1 - cairo/.tool-versions | 1 + cairo/Scarb.lock | 16 +- cairo/Scarb.toml | 15 +- cairo/src/HSTK.cairo | 17 + cairo/src/HashToken.cairo | 155 ------- cairo/src/MultiSigL2.cairo | 119 ++++++ cairo/src/components/AccessRegistry.cairo | 165 ++++++++ cairo/src/components/BlackListed.cairo | 76 ++++ cairo/src/components/Pausable.cairo | 396 ++++++++++++++++++ .../components/utils/FallbackAdmin2Step.cairo | 181 ++++++++ .../components/utils/SuperAdmin2Step.cairo | 184 ++++++++ cairo/src/helpers/constants.cairo | 4 + cairo/src/interfaces/IHashToken.cairo | 25 -- cairo/src/interfaces/IaccessRegistry.cairo | 9 + cairo/src/interfaces/IblackListed.cairo | 7 + .../src/interfaces/IfallbackAdmin2Step.cairo | 13 + cairo/src/interfaces/Ipausable.cairo | 24 ++ cairo/src/interfaces/IsuperAdmin2Step.cairo | 12 + cairo/src/lib.cairo | 30 +- 20 files changed, 1243 insertions(+), 207 deletions(-) create mode 100644 cairo/.tool-versions create mode 100644 cairo/src/HSTK.cairo delete mode 100644 cairo/src/HashToken.cairo create mode 100644 cairo/src/MultiSigL2.cairo create mode 100644 cairo/src/components/AccessRegistry.cairo create mode 100644 cairo/src/components/BlackListed.cairo create mode 100644 cairo/src/components/Pausable.cairo create mode 100644 cairo/src/components/utils/FallbackAdmin2Step.cairo create mode 100644 cairo/src/components/utils/SuperAdmin2Step.cairo create mode 100644 cairo/src/helpers/constants.cairo delete mode 100644 cairo/src/interfaces/IHashToken.cairo create mode 100644 cairo/src/interfaces/IaccessRegistry.cairo create mode 100644 cairo/src/interfaces/IblackListed.cairo create mode 100644 cairo/src/interfaces/IfallbackAdmin2Step.cairo create mode 100644 cairo/src/interfaces/Ipausable.cairo create mode 100644 cairo/src/interfaces/IsuperAdmin2Step.cairo diff --git a/cairo/.gitignore b/cairo/.gitignore index 73aa31e..eb5a316 100644 --- a/cairo/.gitignore +++ b/cairo/.gitignore @@ -1,2 +1 @@ target -.snfoundry_cache/ diff --git a/cairo/.tool-versions b/cairo/.tool-versions new file mode 100644 index 0000000..4a51faa --- /dev/null +++ b/cairo/.tool-versions @@ -0,0 +1 @@ +starknet-foundry 0.27.0 diff --git a/cairo/Scarb.lock b/cairo/Scarb.lock index 905bedc..fc4de3f 100644 --- a/cairo/Scarb.lock +++ b/cairo/Scarb.lock @@ -2,19 +2,5 @@ version = 1 [[package]] -name = "cairo" +name = "cairo_starknet" version = "0.1.0" -dependencies = [ - "openzeppelin", - "snforge_std", -] - -[[package]] -name = "openzeppelin" -version = "0.13.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.13.0#978b4e75209da355667d8954d2450e32bd71fe49" - -[[package]] -name = "snforge_std" -version = "0.23.0" -source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.23.0#f2bff8f796763ada77fe6033ec1b034ceee22abd" diff --git a/cairo/Scarb.toml b/cairo/Scarb.toml index abac786..ec24624 100644 --- a/cairo/Scarb.toml +++ b/cairo/Scarb.toml @@ -1,19 +1,16 @@ [package] -name = "cairo" +name = "cairo_starknet" version = "0.1.0" edition = "2023_11" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html [dependencies] -openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.13.0" } -starknet = "2.6.3" -[dev-dependencies] -snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.23.0" } +# ... + +[workspace.dependencies] +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.27.0" } + -[[target.starknet-contract]] -sierra = true -[crate_roots] -src = "cairo" \ No newline at end of file diff --git a/cairo/src/HSTK.cairo b/cairo/src/HSTK.cairo new file mode 100644 index 0000000..2582e58 --- /dev/null +++ b/cairo/src/HSTK.cairo @@ -0,0 +1,17 @@ +// #[starknet::contract] +// pub mod HSTKContract{ + +// use starknet::{get_caller_address,ContractAddress}; +// use components::BlackListed; +// use components::Pausable; + +// component!(path: BlackListedComponent, storage: black, event: SupplyEvent); + + + + + + + + +// } \ No newline at end of file diff --git a/cairo/src/HashToken.cairo b/cairo/src/HashToken.cairo deleted file mode 100644 index 68e3c4d..0000000 --- a/cairo/src/HashToken.cairo +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: MIT - -const MINTER_ROLE: felt252 = selector!("MINTER_ROLE"); -const UPGRADER_ROLE: felt252 = selector!("UPGRADER_ROLE"); - -#[starknet::contract] -mod HashToken { - use starknet::{ClassHash, ContractAddress, get_caller_address}; - use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE}; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use openzeppelin::upgrades::{UpgradeableComponent, interface::IUpgradeable}; - use super::{MINTER_ROLE, UPGRADER_ROLE}; - use cairo::interfaces::IHashToken::{IHashToken, IHashTokenCamel}; - - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); - - #[abi(embed_v0)] - impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl; - #[abi(embed_v0)] - impl AccessControlMixinImpl = - AccessControlComponent::AccessControlMixinImpl; - - impl ERC20InternalImpl = ERC20Component::InternalImpl; - impl AccessControlInternalImpl = AccessControlComponent::InternalImpl; - impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20: ERC20Component::Storage, - #[substorage(v0)] - accesscontrol: AccessControlComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage, - #[substorage(v0)] - upgradeable: UpgradeableComponent::Storage, - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20Event: ERC20Component::Event, - #[flat] - AccessControlEvent: AccessControlComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event, - #[flat] - UpgradeableEvent: UpgradeableComponent::Event, - } - - #[constructor] - fn constructor( - ref self: ContractState, - default_admin: ContractAddress, - minter: ContractAddress, - upgrader: ContractAddress, - ) { - self.erc20.initializer("HashToken", "HASH"); - self.accesscontrol.initializer(); - - self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin); - self.accesscontrol._grant_role(MINTER_ROLE, minter); - self.accesscontrol._grant_role(UPGRADER_ROLE, upgrader); - } - - #[abi(embed_v0)] - impl HashTokenImpl of IHashToken { - fn increase_allowance( - ref self: ContractState, spender: ContractAddress, added_value: u256 - ) -> bool { - self._increase_allowance(spender, added_value) - } - fn decrease_allowance( - ref self: ContractState, spender: ContractAddress, subtracted_value: u256 - ) -> bool { - self._decrease_allowance(spender, subtracted_value) - } - fn permissioned_mint(ref self: ContractState, account: ContractAddress, amount: u256) { - self.accesscontrol.assert_only_role(MINTER_ROLE); - self.erc20._mint(account, amount); - } - fn permissioned_burn(ref self: ContractState, account: ContractAddress, amount: u256) { - self.accesscontrol.assert_only_role(MINTER_ROLE); - self.erc20._burn(get_caller_address(), amount); - } - } - - #[abi(embed_v0)] - impl HashTokenCamelImpl of IHashTokenCamel { - fn permissionedMint(ref self: ContractState, account: ContractAddress, amount: u256) { - HashTokenImpl::permissioned_mint(ref self, account, amount) - } - fn permissionedBurn(ref self: ContractState, account: ContractAddress, amount: u256) { - HashTokenImpl::permissioned_burn(ref self, account, amount) - } - fn increaseAllowance( - ref self: ContractState, spender: ContractAddress, addedValue: u256 - ) -> bool { - HashTokenImpl::increase_allowance(ref self, spender, addedValue) - } - fn decreaseAllowance( - ref self: ContractState, spender: ContractAddress, subtractedValue: u256 - ) -> bool { - HashTokenImpl::decrease_allowance(ref self, spender, subtractedValue) - } - } - - #[abi(embed_v0)] - impl UpgradeableImpl of IUpgradeable { - fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { - self.accesscontrol.assert_only_role(UPGRADER_ROLE); - self.upgradeable._upgrade(new_class_hash); - } - } - - #[generate_trait] - impl InternalImpl of InternalTrait { - /// Internal method for the external [increase_allowance](increase_allowance). - /// Emits an [Approval](Approval) event indicating the updated allowance. - fn _increase_allowance( - ref self: ContractState, spender: ContractAddress, added_value: u256 - ) -> bool { - let caller = get_caller_address(); - self - .erc20 - ._approve( - caller, - spender, - self.erc20.ERC20_allowances.read((caller, spender)) + added_value - ); - true - } - - /// Internal method for the external [decrease_allowance](decrease_allowance). - /// Emits an [Approval](Approval) event indicating the updated allowance. - fn _decrease_allowance( - ref self: ContractState, spender: ContractAddress, subtracted_value: u256 - ) -> bool { - let caller = get_caller_address(); - self - .erc20 - ._approve( - caller, - spender, - self.erc20.ERC20_allowances.read((caller, spender)) - subtracted_value - ); - true - } - } -} diff --git a/cairo/src/MultiSigL2.cairo b/cairo/src/MultiSigL2.cairo new file mode 100644 index 0000000..99064a9 --- /dev/null +++ b/cairo/src/MultiSigL2.cairo @@ -0,0 +1,119 @@ +#[starknet::contract] +pub mod MultiSigL2{ + + use starknet::{ContractAddress,get_caller_address}; + use cairo_starknet::components::AccessRegistry::AccessRegistryComp; + + + component!(path:AccessRegistryComp , storage:access_registry , event:AccessRegistryEvents); + + // Constants + const SIGNER_WINDOW: u64 = 86400; // 24 hours in seconds + const FALLBACK_ADMIN_WINDOW: u64 = 259200; // 72 hours in seconds + const APPROVAL_THRESHOLD: u64 = 60; // 60% of signers must approve + + // Function selectors as constants + const MINT_SELECTOR: felt252 = selector!("add_supported_bridge(ContractAddress)"); + const BURN_SELECTOR: felt252 = selector!("remove_supported_bridge(ContractAddress)"); + const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); + const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); + const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); + const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress)"); + + #[derive(Copy, Drop, Serde, starknet::Store)] + enum TransactionState { + Pending, + Active, + Queued, + Expired, + Executed, + } + + #[derive(Drop, Serde, starknet::Store)] + struct Transaction { + proposer: ContractAddress, + selector: felt252, + params: Array, + proposed_at: u64, + first_sign_at: u64, + approvals: u64, + state: TransactionState, + is_fallback_admin: bool, + } + + #[storage] + struct Storage { + token_contract: ContractAddress, + transactions: LegacyMap, + has_approved: LegacyMap<(u256, ContractAddress), bool>, + transaction_exists: LegacyMap, + fallback_admin_functions: LegacyMap, + signer_functions: LegacyMap, + #[substorage(v0)] + access_registry:AccessRegistryComp::Storage + + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + TransactionProposed: TransactionProposed, + TransactionApproved: TransactionApproved, + TransactionRevoked: TransactionRevoked, + TransactionExecuted: TransactionExecuted, + TransactionExpired: TransactionExpired, + TransactionStateChanged: TransactionStateChanged, + #[flat] + AccessRegistryEvents::AccessRegistryComp::Events + } + + #[derive(Drop, starknet::Event)] + struct TransactionProposed { + tx_id: felt252, + proposer: ContractAddress, + proposed_at: u64, + } + + #[derive(Drop, starknet::Event)] + struct TransactionApproved { + tx_id: felt252, + signer: ContractAddress, + } + + #[derive(Drop, starknet::Event)] + struct TransactionRevoked { + tx_id: felt252, + revoker: ContractAddress, + } + + #[derive(Drop, starknet::Event)] + struct TransactionExecuted { + tx_id: felt252 + } + + #[derive(Drop, starknet::Event)] + struct TransactionExpired { + tx_id: felt252 + } + + #[derive(Drop, starknet::Event)] + struct TransactionStateChanged { + tx_id: felt252, + new_state: TransactionState, + } + + #[constructor] + fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress, fallback_admin:ContractAddress){ + self.access_registry.initializer(super_admin,fallback_admin); + self.token_contract.write(token_l2); + } + + + + + + + + + +} \ No newline at end of file diff --git a/cairo/src/components/AccessRegistry.cairo b/cairo/src/components/AccessRegistry.cairo new file mode 100644 index 0000000..74c60ed --- /dev/null +++ b/cairo/src/components/AccessRegistry.cairo @@ -0,0 +1,165 @@ +#[starknet::component] +pub mod AccessRegistryComp{ + use starknet::{ContractAddress,get_caller_address}; + use cairo::interfaces::IaccessRegistry::IAccessRegistryComponent; + use cairo::components::utils::FallbackAdmin2Step::FallbackAdminTwoStep; + use cairo::components::utils::SuperAdmin2Step::SuperAdminTwoStep; + + + #[storage] + struct Storage{ + total_signers:u256, + signers:LegacyMap::, + } + + #[event] + #[derive(Drop, starknet::event)] + enum Event{ + SignerAdded: SignerAdded, + SignerRemoved: SignerRemoved, + SignerRenounced: SignerRenounced + } + + #[derive(Drop, starknet::Event)] + pub struct SignerAdded{ + #[key] + new_signer:ContractAddress + } + + #[derive(Drop, starknet::Event)] + pub struct SignerRemoved{ + #[key] + removed_signer: ContractAddress + } + + #[derive(Drop, starknet::Event)] + pub struct SignerRenounced{ + #[key] + from:ContractAddress, + #[key] + to:ContractAddress + } + + pub mod Error{ + pub const ZERO_ADDRESS:felt252 = 'Zero Address'; + pub const SuperAdminIsRestricted:felt252='Super Admin Is Restricted'; + pub const Already_Signer:felt252='Already a Signer'; + pub const SuperAdminCannotRemoved:felt252='Super Admin Cannot Removed'; + pub const NonExistingSigner:felt252='Non Existing Signer'; + + } + + + + #[embeddable_as(AccessRegistry)] + impl AccessRegistyImpl< + TContractState, + +HasComponent, + impl SuperAdminTwoStep:SuperAdminTwoStep::HasComponent, + impl FallbackAdminTwoStep:FallbackAdminTwoStep::HasComponent + > of IAccessRegistryComponent>{ + + fn is_signer(self:@ComponentState,account:ContractAddress)->bool{ + self.signers.read(account) + } + + fn add_signer(ref self: ComponentState, new_signer:ContractAddress){ + + assert(!new_signer.is_zero(), Error::ZERO_ADDRESS); + asser(!self.is_signer(new_signer),Error::Already_Signer); + + let super_admin_comp = get_dep_component!(@self,SuperAdminTwoStep); + super_admin_comp.assert_only_super_admin(); + self.signers.write(new_signer,true); + self.total_signers.write(self.total_signers.read()+1); + self.emit( + SignerAdded{ + new_signer:existing_owner + }); + + } + + fn remove_signer(ref self: ComponentState,existing_owner:ContractAddress){ + + assert(!existing_owner.is_zero(), Error::ZERO_ADDRESS); + asser(self.is_signer(existing_owner),Error::Not_A_Signer); + + let super_admin_comp = get_dep_component!(@self,SuperAdminTwoStep); + + let super_admin:ContractAddress = super_admin_comp.super_admin(); + assert(existing_owner!=super_admin,Error::SuperAdminCannotRemoved); + super_admin_comp.assert_only_super_admin(); + + + self.signers.write(existing_owner,false); + self.total_signers.write(self.total_signers.read()-1); + + self.emit( + SignerRemoved{ + remove_signer:existing_owner + }); + } + fn renounce_signership(ref self: ComponentState,signer:ContractAddress){ + + assert(!signer.is_zero(), Error::ZERO_ADDRESS); //check for zero address + + let caller:ContractAddress = get_caller_address(); + assert(self.is_signer(caller),Error::Not_A_Signer); //only be calleable by signer + assert(!self.is_signer(signer),Error::Already_Signer); //new signer cannot be existing signer + + let super_admin_comp = get_dep_component!(@self,SuperAdminTwoStep); + let super_admin:ContractAddress = super_admin_comp.super_admin(); + assert(existing_owner!=super_admin,Error::SuperAdminCannotRemoved); //signer cannot be remove + // check it needs to be existing owner + _renounce_signership(caller,signer); + } + fn accept_super_adminship(ref self:ComponentState){ + + let caller:ContractAddress = get_caller_address(); + let super_admin_comp = get_dep_component!(ref self, SuperAdminTwoStep); + let super_admin:ContractAddress = super_admin_comp.super_admin(); + super_admin_comp._accept_super_adminship(); + self._renounce_signership(caller,super_admin); + } + + #[generate_trait] + pub impl InternalImpl< + TContractState, +HasComponent + > of InternalTrait + + fn initializer(ref self: ComponentState,super_admin:ContractAddress, fallback_admin:ContractAddress){ + let super_admin_comp = get_dep_component!(ref self,SuperAdminTwoStep); + let fallback_admin_comp = get_dep_component!(ref self,FallbackAdminTwoStep); + super_admin_comp.initializer(super_admin); + fallback_admin_comp.initializer(fallback_admin); + self.total_signers.write(1); + self.signers.write(super_admin,true); + } + + fn _renounce_signership(ref self:ComponentState,from:ContractAddress, to:ContractAddress){ + + self.signers.write(from,false); + self.signers.write(to,true); + + self.emit( + SignerRenounced{ + from:from, + to:to + }) + + } + } + + + + + + + + + + + + + +} \ No newline at end of file diff --git a/cairo/src/components/BlackListed.cairo b/cairo/src/components/BlackListed.cairo new file mode 100644 index 0000000..69c1ad0 --- /dev/null +++ b/cairo/src/components/BlackListed.cairo @@ -0,0 +1,76 @@ +#[starknet::component] +pub mod BlackListedComponent { + use starknet::{ContractAddress,get_caller_address}; + use core::panic_with_felt252; + + use cairo::interfaces::IblackListed::IBlackListedComponent; + + #[storage] + struct Storage { + blackListedAccount: LegacyMap::, + multiSig: ContractAddress + } + + // Events + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + NewAccountBlackListed: NewAccountBlackListed, + RemovedAccountBlackListed: RemovedAccountBlackListed, + } + + #[derive(Drop, starknet::Event)] + pub struct NewAccountBlackListed{ + #[key] + blackListed_account:ContractAddress + } + + #[derive(Drop,starknet::Event)] + pub struct RemovedAccountBlackListed{ + #[key] + removed_Account: ContractAddress + } + + pub mod Error{ + pub const AccountBlackListed:felt252 ='Account is BlackListed'; + pub const RestrictedToMultiSig:felt252 ='Restricted To MultiSig Contract'; + } + + #[generate_trait] + impl InternalFunctionBlackListed> + of InternalFunctionBlackListedTraits{ + fn initializer(ref self: ComponentState , multiSig: ContractAddress){ + self.multiSig.write(multiSig); + } + + fn _only_multiSig(self:@ComponentState){ + assert(get_caller_address() != self.multiSig.read(),Error::RestrictedToMultiSig); + } + + fn _not_blackListed(self:@ComponentState,check:ContractAddress){ + let flag: bool = self.blackListedAccount.read(check); + assert(flag,Error::AccountBlackListed); + } + + fn blackList_account(ref self : ComponentState, account:ContractAddress){ + self._only_multiSig(); + self.blackListedAccount.write(account,true); + self.emit(NewAccountBlackListed{ + blackListed_account:account + }); + } + + fn remove_blackListed_account(ref self: ComponentState, account : ContractAddress){ + self._only_multiSig(); + self.blackListedAccount.write(account,false); + self.emit(RemovedAccountBlackListed{ + removed_Account:account + }); + } + + fn is_blackListed_account(self :@ComponentState, account:ContractAddress)-> bool { + return self.blackListedAccount.read(account); + } + + } +} \ No newline at end of file diff --git a/cairo/src/components/Pausable.cairo b/cairo/src/components/Pausable.cairo new file mode 100644 index 0000000..8576953 --- /dev/null +++ b/cairo/src/components/Pausable.cairo @@ -0,0 +1,396 @@ +// // Define the pause states using an enum +// #[starknet::component] +// pub mod Pausable { +// use cairo_starknet::helpers::constants; +// use cairo_starknet::interfaces::Ipausable::IPausable; + +// #[derive(Drop, Copy, Serde)] +// pub enum PauseState { +// Active, +// PartialPause, +// FullPause +// } + +// #[storage] +// struct Storage { +// current_state: PauseState +// } + +// #[event] +// #[derive(Drop, starknet::Event)] +// enum Event { +// PauseStateChanged: PauseStateChanged, +// } + +// #[derive(Drop, starknet::Event)] +// struct PauseStateChanged { +// new_state: PauseState, +// } + +// #[derive(Drop, PartialEq)] +// enum PausableError { +// EnforcedPause, +// EnforcedPartialPause, +// InvalidStateChange, +// } + +// fn panic_with_felt252(err: felt252) { +// core::panic_with_felt252(err) +// } + +// impl PausableErrorIntoFelt252 of Into { +// fn into(self: PausableError) -> felt252 { +// match self { +// PausableError::EnforcedPause => 'Contract is fully paused', +// PausableError::EnforcedPartialPause => 'Contract is partially paused', +// PausableError::InvalidStateChange => 'Invalid state change' +// } +// } +// } + +// #[embeddable_as(Pausable)] +// impl PausableImpl< +// TContractState, +// impl TContractStateDestruct: Drop, +// impl TContractStateComponent: HasComponent +// > of IPausable> { +// fn get_current_state(self: @ComponentState) -> PauseState { +// self.current_state.read() +// } + +// fn is_active(self: @ComponentState) -> bool { +// match self.current_state.read() { +// PauseState::Active => true, +// _ => false +// } +// } + +// fn is_partial_paused(self: @ComponentState) -> bool { +// match self.current_state.read() { +// PauseState::PartialPause => true, +// _ => false +// } +// } + +// fn is_full_paused(self: @ComponentState) -> bool { +// match self.current_state.read() { +// PauseState::FullPause => true, +// _ => false +// } +// } +// } + +// #[generate_trait] +// impl InternalFunctions< +// TContractState, +// impl TContractStateDestruct: Drop, +// impl TContractStateComponent: HasComponent +// > of InternalFunctionsTrait { +// fn initializer(ref self: ComponentState) { +// self.current_state.write(PauseState::Active); +// } + +// fn _require_active(self: @ComponentState) { +// let current_state = self.current_state.read(); +// match current_state { +// PauseState::Active => {}, +// PauseState::PartialPause => { +// panic_with_felt252(PausableError::EnforcedPartialPause.into()) +// }, +// PauseState::FullPause => { +// panic_with_felt252(PausableError::EnforcedPause.into()) +// } +// } +// } + +// fn _require_active_or_partial(self: @ComponentState) { +// let current_state = self.current_state.read(); +// match current_state { +// PauseState::Active => {}, +// PauseState::PartialPause => {}, +// PauseState::FullPause => { +// panic_with_felt252(PausableError::EnforcedPause.into()) +// } +// } +// } + +// fn _update_operational_state( +// ref self: ComponentState, +// new_state: PauseState +// ) { +// self.current_state.write(new_state); + +// // Emit state change event +// self.emit(Event::PauseStateChanged( +// PauseStateChanged { new_state } +// )); +// } +// } +// } + + + +// #[starknet::component] +// pub mod Pausable { +// use starknet::ContractAddress; +// use cairo_starknet::helpers::constants; +// use cairo_starknet::interfaces::Ipausable::IPausable; + + +// #[derive(Drop, Copy, Serde)] +// pub enum PauseState { +// Active, +// PartialPause, +// FullPause +// } + +// #[storage] +// struct Storage { +// current_state: PauseState +// } + +// #[event] +// #[derive(Drop, starknet::Event)] +// enum Event { +// PauseStateChanged: PauseStateChanged, +// } + +// #[derive(Drop, starknet::Event)] +// struct PauseStateChanged { +// new_state: PauseState, +// } + +// #[derive(Drop, PartialEq)] +// enum PausableError { +// EnforcedPause, +// EnforcedPartialPause, +// InvalidStateChange, +// } + +// fn panic_with_felt252(err: felt252) { +// core::panic_with_felt252(err) +// } + +// impl PausableErrorIntoFelt252 of Into { +// fn into(self: PausableError) -> felt252 { +// match self { +// PausableError::EnforcedPause => 'Contract is fully paused', +// PausableError::EnforcedPartialPause => 'Contract is partially paused', +// PausableError::InvalidStateChange => 'Invalid state change' +// } +// } +// } + +// #[embeddable_as(Pausable)] +// impl PausableImpl< +// TContractState, +// impl TContractStateDestruct: Drop, +// impl TContractStateComponent: HasComponent +// > of IPausable> { +// fn get_current_state(self: @ComponentState) -> PauseState { +// let state = self.current_state.read(); +// state +// } + +// fn is_active(self: @ComponentState) -> bool { +// match self.get_current_state() { +// PauseState::Active => true, +// _ => false +// } +// } + +// fn is_partial_paused(self: @ComponentState) -> bool { +// match self.get_current_state() { +// PauseState::PartialPause => true, +// _ => false +// } +// } + +// fn is_full_paused(self: @ComponentState) -> bool { +// match self.get_current_state() { +// PauseState::FullPause => true, +// _ => false +// } +// } +// } + +// #[generate_trait] +// impl InternalFunctions< +// TContractState, +// impl TContractStateDestruct: Drop, +// impl TContractStateComponent: HasComponent +// > of InternalFunctionsTrait { +// fn initializer(ref self: ComponentState) { +// self.current_state.write(PauseState::Active); +// } + +// fn _require_active(self: @ComponentState) { +// match self.get_current_state() { +// PauseState::Active => {}, +// PauseState::PartialPause => { +// panic_with_felt252(PausableError::EnforcedPartialPause.into()) +// }, +// PauseState::FullPause => { +// panic_with_felt252(PausableError::EnforcedPause.into()) +// } +// } +// } + +// fn _require_active_or_partial(self: @ComponentState) { +// match self.get_current_state() { +// PauseState::Active => {}, +// PauseState::PartialPause => {}, +// PauseState::FullPause => { +// panic_with_felt252(PausableError::EnforcedPause.into()) +// } +// } +// } + +// fn _update_operational_state( +// ref self: ComponentState, +// new_state: PauseState +// ) { +// self.current_state.write(new_state); + +// // Emit state change event +// self.emit(Event::PauseStateChanged( +// PauseStateChanged { new_state } +// )); +// } +// } +// } + + + + + +use starknet::ContractAddress; +use core::starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; + +#[starknet::interface] +trait IPausable { + fn get_current_state(self: @TContractState) -> PauseState; + fn is_active(self: @TContractState) -> bool; + fn is_partial_paused(self: @TContractState) -> bool; + fn is_full_paused(self: @TContractState) -> bool; +} + +#[derive(Drop, Copy, Serde)] +pub enum PauseState { + Active, + PartialPause, + FullPause +} + +#[starknet::component] +pub mod Pausable { + use super::{PauseState, IPausable}; + use starknet::ContractAddress; + use core::starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; + + #[storage] + struct Storage { + current_state: PauseState + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + PauseStateChanged: PauseStateChanged, + } + + #[derive(Drop, starknet::Event)] + struct PauseStateChanged { + new_state: PauseState, + } + + #[derive(Drop, PartialEq)] + enum PausableError { + EnforcedPause, + EnforcedPartialPause, + InvalidStateChange, + } + + fn panic_with_felt252(err: felt252) { + core::panic_with_felt252(err) + } + + impl PausableErrorIntoFelt252 of Into { + fn into(self: PausableError) -> felt252 { + match self { + PausableError::EnforcedPause => 'Contract is fully paused', + PausableError::EnforcedPartialPause => 'Contract is partially paused', + PausableError::InvalidStateChange => 'Invalid state change' + } + } + } + + #[embeddable_as(Pausable)] + impl PausableImpl< + TContractState, + impl TContractStateDestruct: Drop, + impl TContractStateComponent: HasComponent + > of IPausable> { + fn get_current_state(self: @ComponentState) -> PauseState { + let current_state = StorageMemberAccessTrait::::read(self.current_state.address()); + current_state + } + + fn is_active(self: @ComponentState) -> bool { + match self.get_current_state() { + PauseState::Active => true, + _ => false + } + } + + fn is_partial_paused(self: @ComponentState) -> bool { + match self.get_current_state() { + PauseState::PartialPause => true, + _ => false + } + } + + fn is_full_paused(self: @ComponentState) -> bool { + match self.get_current_state() { + PauseState::FullPause => true, + _ => false + } + } + } + + #[generate_trait] + impl InternalFunctions< + TContractState, + impl TContractStateDestruct: Drop, + impl TContractStateComponent: HasComponent + > of InternalFunctionsTrait { + fn initializer(ref self: ComponentState) { + StorageMemberAccessTrait::::write( + self.current_state.address(), + PauseState::Active + ); + } + + fn _require_active(self: @ComponentState) { + match self.get_current_state() { + PauseState::Active => {}, + PauseState::PartialPause => { + panic_with_felt252(PausableError::EnforcedPartialPause.into()) + }, + PauseState::FullPause => { + panic_with_felt252(PausableError::EnforcedPause.into()) + } + } + } + + fn _require_active_or_partial(self: @ComponentState) { + match self.get_current_state() { + PauseState::Active => {}, + PauseState::PartialPause => {}, + PauseState::FullPause => { + panic_with_felt252(PausableError::EnforcedPause.into()) + } + } + } + + fn _update_operational_ \ No newline at end of file diff --git a/cairo/src/components/utils/FallbackAdmin2Step.cairo b/cairo/src/components/utils/FallbackAdmin2Step.cairo new file mode 100644 index 0000000..c4135b0 --- /dev/null +++ b/cairo/src/components/utils/FallbackAdmin2Step.cairo @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts for Cairo v0.19.0 (access/ownable/ownable.cairo) + +/// # Ownable Component +/// +/// The Ownable component provides a basic access control mechanism, where +/// there is an account (an fallback_admin) that can be granted exclusive access to +/// specific functions. +/// +/// The initial fallback_admin can be set by using the `initializer` function in +/// construction time. This can later be changed with `transfer_fallback_adminship`. +/// +/// The component also offers functionality for a two-step fallback_adminship +/// transfer where the new fallback_admin first has to accept their fallback_adminship to +/// finalize the transfer. +#[starknet::component] +pub mod FallbackAdminTwoStep { + use core::num::traits::Zero; + use cairo::interfaces::IfallbackAdmin2Step::IFallbackAdminTwoStep; + // use cairo_starknet::interfaces::IsuperAdmin2Step; + use cairo::interfaces::IfallbackAdmin2Step; + + use starknet::ContractAddress; + use starknet::{get_caller_address,get_block_timestamp}; + + #[storage] + pub struct Storage { + pub fallback_admin: ContractAddress, + pub pending_admin: ContractAddress, + pub handover_expires: u64 + } + + #[event] + #[derive(Drop, PartialEq, starknet::Event)] + pub enum Event { + FallbackOwnershipTransferred: FallbackOwnershipTransferred, + FallbackOwnershipTransferStarted: FallbackOwnershipTransferStarted + } + + #[derive(Drop, PartialEq, starknet::Event)] + pub struct FallbackOwnershipTransferred { + #[key] + pub previous_fallback_admin: ContractAddress, + #[key] + pub new_fallback_admin: ContractAddress, + } + + #[derive(Drop, PartialEq, starknet::Event)] + pub struct FallbackOwnershipTransferStarted { + #[key] + pub previous_fallback_admin: ContractAddress, + #[key] + pub new_fallback_admin: ContractAddress, + + } + + pub mod Errors { + pub const NOT_OWNER: felt252 = 'Caller is not FB admin'; + pub const NOT_PENDING_OWNER: felt252 = 'Caller is not pending FB admin'; + pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; + pub const ZERO_ADDRESS_OWNER: felt252 = 'New FB is the zero address'; + pub const HANDOVER_EXPIRED: felt252 = 'Super Admin Ownership expired'; + } + + /// Adds support for two step fallback_adminship transfer. + #[embeddable_as(FallbackAdminTwoStepImpl)] + impl FallbackAdminTwoStep< + TContractState, +HasComponent + > of IfallbackAdmin2Step::IFallbackAdminTwoStep> { + /// Returns the address of the current fallback_admin. + fn fallback_admin(self: @ComponentState) -> ContractAddress { + self.fallback_admin.read() + } + + /// Returns the address of the pending fallback_admin. + fn pending_fallback_admin(self: @ComponentState) -> ContractAddress { + self.pending_admin.read() + } + + //Returns the handover expiry of the pending fallback_admin + fn fallback_handover_expires_at(self:@ComponentState ) -> u64 { + self.handover_expires.read() + } + + /// Finishes the two-step fallback_adminship transfer process by accepting the fallback_adminship. + /// Can only be called by the pending fallback_admin. + /// + /// Requirements: + /// + /// - The caller is the pending fallback_admin. + /// + /// Emits an `OwnershipTransferred` event. + fn accept_fallback_adminship(ref self: ComponentState) { + let caller = get_caller_address(); + let pending_fallback_admin = self.pending_admin.read(); + let fallback_adminship_expires_at:u64 = self.handover_expires.read(); + assert(caller == pending_fallback_admin, Errors::NOT_PENDING_OWNER); + assert(get_block_timestamp()<= fallback_adminship_expires_at,Errors::HANDOVER_EXPIRED); + self._transfer_fallback_adminship(pending_fallback_admin); + } + + /// Starts the two-step fallback_adminship transfer process by setting the pending fallback_admin. + /// + /// Requirements: + /// + /// - The caller is the contract fallback_admin. + /// + /// Emits an `OwnershipTransferStarted` event. + fn transfer_fallback_adminship( + ref self: ComponentState, new_fallback_admin: ContractAddress + ) { + self.assert_only_fallback_admin(); + self._propose_fallback_admin(new_fallback_admin); + } + + /// Returns the time for which handover is valid for pending fallback_admin. + fn fallback_admin_ownership_valid_for(self:@ComponentState)->u64{ + 72*3600 + } + + } + + #[generate_trait] + pub impl InternalImpl< + TContractState, +HasComponent + > of InternalTrait { + /// Sets the contract's initial fallback_admin. + /// + /// This function should be called at construction time. + fn initializer(ref self: ComponentState, fallback_admin: ContractAddress) { + self._transfer_fallback_adminship(fallback_admin); + } + + /// Panics if called by any account other than the fallback_admin. Use this + /// to restrict access to certain functions to the fallback_admin. + fn assert_only_fallback_admin(self: @ComponentState) { + let fallback_admin = self.fallback_admin.read(); + let caller = get_caller_address(); + assert(!caller.is_zero(), Errors::ZERO_ADDRESS_CALLER); + assert(caller == fallback_admin, Errors::NOT_OWNER); + } + + /// Transfers fallback_adminship of the contract to a new address and resets + /// the pending fallback_admin to the zero address. + /// + /// Internal function without access restriction. + /// + /// Emits an `OwnershipTransferred` event. + fn _transfer_fallback_adminship( + ref self: ComponentState, new_fallback_admin: ContractAddress + ) { + self.pending_admin.write(Zero::zero()); + self.handover_expires.write(0); + + let previous_fallback_admin: ContractAddress = self.fallback_admin.read(); + self.fallback_admin.write(new_fallback_admin); + self + .emit( + FallbackOwnershipTransferred{ previous_fallback_admin: previous_fallback_admin, new_fallback_admin: new_fallback_admin } + ); + } + + /// Sets a new pending fallback_admin. + /// + /// Internal function without access restriction. + /// + /// Emits an `OwnershipTransferStarted` event. + fn _propose_fallback_admin(ref self: ComponentState, new_fallback_admin: ContractAddress) { + let previous_fallback_admin = self.fallback_admin.read(); + self.pending_admin.write(new_fallback_admin); + let fallback_adminship_expires_at = get_block_timestamp() + self.fallback_admin_ownership_valid_for(); + self.handover_expires.write(fallback_adminship_expires_at); + self + .emit( + FallbackOwnershipTransferStarted { + previous_fallback_admin: previous_fallback_admin, new_fallback_admin: new_fallback_admin + } + ); + } + } +} \ No newline at end of file diff --git a/cairo/src/components/utils/SuperAdmin2Step.cairo b/cairo/src/components/utils/SuperAdmin2Step.cairo new file mode 100644 index 0000000..ae4f9f5 --- /dev/null +++ b/cairo/src/components/utils/SuperAdmin2Step.cairo @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts for Cairo v0.19.0 (access/ownable/ownable.cairo) + +/// # Ownable Component +/// +/// The Ownable component provides a basic access control mechanism, where +/// there is an account (an super_admin) that can be granted exclusive access to +/// specific functions. +/// +/// The initial super_admin can be set by using the `initializer` function in +/// construction time. This can later be changed with `transfer_super_adminship`. +/// +/// The component also offers functionality for a two-step super_adminship +/// transfer where the new super_admin first has to accept their super_adminship to +/// finalize the transfer. +#[starknet::component] +pub mod SuperAdminTwoStep { + use core::num::traits::Zero; + use cairo::interfaces::IsuperAdmin2Step::ISuperAdminTwoStep; + // use cairo_starknet::interfaces::IsuperAdmin2Step; + use cairo::interfaces::IsuperAdmin2Step; + + use starknet::ContractAddress; + use starknet::{get_caller_address,get_block_timestamp}; + + #[storage] + pub struct Storage { + pub super_admin: ContractAddress, + pub pending_admin: ContractAddress, + pub handover_expires: u64 + } + + #[event] + #[derive(Drop, PartialEq, starknet::Event)] + pub enum Event { + SuperOwnershipTransferred: SuperOwnershipTransferred, + SuperOwnershipTransferStarted: SuperOwnershipTransferStarted + } + + #[derive(Drop, PartialEq, starknet::Event)] + pub struct SuperOwnershipTransferred { + #[key] + pub previous_super_admin: ContractAddress, + #[key] + pub new_super_admin: ContractAddress, + } + + #[derive(Drop, PartialEq, starknet::Event)] + pub struct SuperOwnershipTransferStarted { + #[key] + pub previous_super_admin: ContractAddress, + #[key] + pub new_super_admin: ContractAddress, + + } + + pub mod Errors { + pub const NOT_OWNER: felt252 = 'Caller is not super admin'; + pub const NOT_PENDING_OWNER: felt252 = 'Caller not pending super admin'; + pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; + pub const ZERO_ADDRESS_OWNER: felt252 = 'Calldata consist zero address'; + pub const HANDOVER_EXPIRED: felt252 = 'Super Admin Ownership expired'; + } + + /// Adds support for two step super_adminship transfer. + #[embeddable_as(SuperAdminTwoStepImpl)] + impl SuperAdminTwoStep< + TContractState, + +HasComponent + > of IsuperAdmin2Step::ISuperAdminTwoStep> { + /// Returns the address of the current super_admin. + fn super_admin(self: @ComponentState) -> ContractAddress { + self.super_admin.read() + } + + /// Returns the address of the pending super_admin. + fn pending_super_admin(self: @ComponentState) -> ContractAddress { + self.pending_admin.read() + } + + //Returns the handover expiry of the pending super_admin + fn super_handover_expires_at(self:@ComponentState ) -> u64 { + self.handover_expires.read() + } + + + /// Starts the two-step super_adminship transfer process by setting the pending super_admin. + /// + /// Requirements: + /// + /// - The caller is the contract super_admin. + /// + /// Emits an `OwnershipTransferStarted` event. + fn transfer_super_adminship( + ref self: ComponentState, new_super_admin: ContractAddress + ) { + self.assert_only_super_admin(); + self._propose_super_admin(new_super_admin); + } + + /// Returns the time for which handover is valid for pending super_admin. + fn super_admin_ownership_valid_for(self:@ComponentState)->u64{ + 72*3600 + } + + } + + #[generate_trait] + pub impl InternalImpl< + TContractState, + +HasComponent + > of InternalTrait { + /// Sets the contract's initial super_admin. + /// + /// This function should be called at construction time. + fn initializer(ref self: ComponentState, super_admin: ContractAddress) { + self._transfer_super_adminship(super_admin); + } + + /// Panics if called by any account other than the super_admin. Use this + /// to restrict access to certain functions to the super_admin. + fn assert_only_super_admin(self: @ComponentState) { + let super_admin = self.super_admin.read(); + let caller = get_caller_address(); + assert(!caller.is_zero(), Errors::ZERO_ADDRESS_CALLER); + assert(caller == super_admin, Errors::NOT_OWNER); + } + + /// Finishes the two-step super_adminship transfer process by accepting the super_adminship. + /// Can only be called by the pending super_admin. + /// + /// Requirements: + /// + /// - The caller is the pending super_admin. + /// + /// Emits an `OwnershipTransferred` event. + fn _accept_super_adminship(ref self: ComponentState) { + let caller = get_caller_address(); + let pending_super_admin = self.pending_admin.read(); + let super_adminship_expires_at:u64 = self.handover_expires.read(); + assert(caller == pending_super_admin, Errors::NOT_PENDING_OWNER); + assert(get_block_timestamp()<= super_adminship_expires_at,Errors::HANDOVER_EXPIRED); + self._transfer_super_adminship(pending_super_admin); + } + + /// Transfers super_adminship of the contract to a new address and resets + /// the pending super_admin to the zero address. + /// + /// Internal function without access restriction. + /// + /// Emits an `OwnershipTransferred` event. + fn _transfer_super_adminship( + ref self: ComponentState, new_super_admin: ContractAddress + ) { + self.pending_admin.write(Zero::zero()); + self.handover_expires.write(0); + + let previous_super_admin: ContractAddress = self.super_admin.read(); + self.super_admin.write(new_super_admin); + self + .emit( + SuperOwnershipTransferred { previous_super_admin: previous_super_admin, new_super_admin: new_super_admin } + ); + } + + /// Sets a new pending super_admin. + /// + /// Internal function without access restriction. + /// + /// Emits an `OwnershipTransferStarted` event. + fn _propose_super_admin(ref self: ComponentState, new_super_admin: ContractAddress) { + let previous_super_admin = self.super_admin.read(); + self.pending_admin.write(new_super_admin); + let super_adminship_expires_at = get_block_timestamp() + self.super_admin_ownership_valid_for(); + self.handover_expires.write(super_adminship_expires_at); + self + .emit( + SuperOwnershipTransferStarted { + previous_super_admin: previous_super_admin, new_super_admin: new_super_admin + } + ); + } + } +} \ No newline at end of file diff --git a/cairo/src/helpers/constants.cairo b/cairo/src/helpers/constants.cairo new file mode 100644 index 0000000..a0df7f4 --- /dev/null +++ b/cairo/src/helpers/constants.cairo @@ -0,0 +1,4 @@ + +pub const Active: felt252 = 0; +pub const PartialPause: felt252 = 1; +pub const FullPause: felt252 = 2; diff --git a/cairo/src/interfaces/IHashToken.cairo b/cairo/src/interfaces/IHashToken.cairo deleted file mode 100644 index 047b9dd..0000000 --- a/cairo/src/interfaces/IHashToken.cairo +++ /dev/null @@ -1,25 +0,0 @@ -use starknet::ContractAddress; - -#[starknet::interface] -pub trait IHashToken { - fn increase_allowance( - ref self: TContractState, spender: ContractAddress, added_value: u256 - ) -> bool; - fn decrease_allowance( - ref self: TContractState, spender: ContractAddress, subtracted_value: u256 - ) -> bool; - fn permissioned_mint(ref self: TContractState, account: ContractAddress, amount: u256); - fn permissioned_burn(ref self: TContractState, account: ContractAddress, amount: u256); -} - -#[starknet::interface] -pub trait IHashTokenCamel { - fn permissionedMint(ref self: TContractState, account: ContractAddress, amount: u256); - fn permissionedBurn(ref self: TContractState, account: ContractAddress, amount: u256); - fn increaseAllowance( - ref self: TContractState, spender: ContractAddress, addedValue: u256 - ) -> bool; - fn decreaseAllowance( - ref self: TContractState, spender: ContractAddress, subtractedValue: u256 - ) -> bool; -} diff --git a/cairo/src/interfaces/IaccessRegistry.cairo b/cairo/src/interfaces/IaccessRegistry.cairo new file mode 100644 index 0000000..ba79627 --- /dev/null +++ b/cairo/src/interfaces/IaccessRegistry.cairo @@ -0,0 +1,9 @@ +use starknet::ContractAddress; +#[starknet::interface] +pub trait IAccessRegistryComponent { + fn add_signer(ref self:TContractState, new_signer:ContractAddress); + fn remove_signer(ref self: TContractState,existing_owner: ContractAddress); + fn renounce_signership(ref self: TContractState,signer: ContractAddress); + fn is_signer(self :@TContractState,account:ContractAddress)->bool; + fn accept_super_adminship(ref self:TContractState); +} \ No newline at end of file diff --git a/cairo/src/interfaces/IblackListed.cairo b/cairo/src/interfaces/IblackListed.cairo new file mode 100644 index 0000000..fcd6c7e --- /dev/null +++ b/cairo/src/interfaces/IblackListed.cairo @@ -0,0 +1,7 @@ +use starknet::ContractAddress; +#[starknet::interface] +pub trait IBlackListedComponent { + fn blackList_account(ref self:TContractState, account:ContractAddress); + fn remove_blackListed_account(ref self: TContractState,account: ContractAddress); + fn is_blackListed_account(self: @TContractState) -> bool; +} \ No newline at end of file diff --git a/cairo/src/interfaces/IfallbackAdmin2Step.cairo b/cairo/src/interfaces/IfallbackAdmin2Step.cairo new file mode 100644 index 0000000..faa0ff4 --- /dev/null +++ b/cairo/src/interfaces/IfallbackAdmin2Step.cairo @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +use starknet::ContractAddress; + + +#[starknet::interface] +pub trait IFallbackAdminTwoStep { + fn fallback_admin(self: @TState) -> ContractAddress; + fn pending_fallback_admin(self: @TState) -> ContractAddress; + fn accept_fallback_adminship(ref self: TState); + fn transfer_fallback_adminship(ref self: TState, new_fallback_admin: ContractAddress); + fn fallback_admin_ownership_valid_for(self:@TState)->u64; + fn fallback_handover_expires_at(self: @TState)->u64; +} \ No newline at end of file diff --git a/cairo/src/interfaces/Ipausable.cairo b/cairo/src/interfaces/Ipausable.cairo new file mode 100644 index 0000000..0a92e3d --- /dev/null +++ b/cairo/src/interfaces/Ipausable.cairo @@ -0,0 +1,24 @@ +use cairo_starknet::helpers::constants; +// Define the pause states using an enum +#[derive(Drop, Copy, Serde)] +pub enum PauseState { + Active, + PartialPause, + FullPause +} + +#[starknet::interface] +pub trait IPausable{ + fn get_current_state(self: @T1) -> PauseState; + fn is_active(self: @T1) -> bool; + fn is_partial_paused(self: @T1) -> bool; + fn is_full_paused(self: @T1) -> bool; +} + +fn get_state_felt(state: PauseState) -> felt252 { + match state { + PauseState::Active => constants::Active, + PauseState::PartialPause => constants::PartialPause, + PauseState::FullPause => constants::FullPause + } +} \ No newline at end of file diff --git a/cairo/src/interfaces/IsuperAdmin2Step.cairo b/cairo/src/interfaces/IsuperAdmin2Step.cairo new file mode 100644 index 0000000..d7535b1 --- /dev/null +++ b/cairo/src/interfaces/IsuperAdmin2Step.cairo @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +use starknet::ContractAddress; + + +#[starknet::interface] +pub trait ISuperAdminTwoStep { + fn super_admin(self: @TState) -> ContractAddress; + fn pending_super_admin(self: @TState) -> ContractAddress; + fn transfer_super_adminship(ref self: TState, new_super_admin: ContractAddress); + fn super_admin_ownership_valid_for(self:@TState)->u64; + fn super_handover_expires_at(self: @TState)->u64; +} \ No newline at end of file diff --git a/cairo/src/lib.cairo b/cairo/src/lib.cairo index f46683e..b1ab5b5 100644 --- a/cairo/src/lib.cairo +++ b/cairo/src/lib.cairo @@ -1,4 +1,30 @@ +// pub mod interfaces{ +// mod IPausable; +// mod IBlackListed; +// } +// pub mod components{ +// mod BlackListed; +// mod Pausable; +// } +pub mod components{ + pub mod Pausable; + pub mod BlackListed; + pub mod AccessRegistry; + pub mod utils{ + pub mod SuperAdmin2Step; + pub mod FallbackAdmin2Step; + } + } pub mod interfaces { - pub mod IHashToken; + pub mod Ipausable; + pub mod IblackListed; + pub mod IaccessRegistry; + pub mod IsuperAdmin2Step; + pub mod IfallbackAdmin2Step; } -pub mod HashToken; +pub mod helpers { + pub mod constants; +} + +pub mod HSTK; +pub mod MultiSigl2; \ No newline at end of file From 09701e8d9e94d86f043c4b615f38d2792ed641ca Mon Sep 17 00:00:00 2001 From: Saurabh Date: Tue, 12 Nov 2024 18:24:07 +0530 Subject: [PATCH 2/8] [BUG_FIX] fixed issues with components [DONE] --- cairo/Scarb.lock | 2 +- cairo/Scarb.toml | 10 +- cairo/src/HSTK.cairo | 8 +- cairo/src/MultiSigL2.cairo | 77 ++- cairo/src/components/AccessRegistry.cairo | 211 +++---- cairo/src/components/BlackListed.cairo | 93 +-- cairo/src/components/Pausable.cairo | 566 +++++++++--------- .../{utils => }/SuperAdmin2Step.cairo | 39 +- .../components/utils/FallbackAdmin2Step.cairo | 35 +- cairo/src/helpers/constants.cairo | 1 - cairo/src/interfaces/IaccessRegistry.cairo | 12 +- cairo/src/interfaces/IblackListed.cairo | 8 +- .../src/interfaces/IfallbackAdmin2Step.cairo | 6 +- cairo/src/interfaces/Ipausable.cairo | 6 +- cairo/src/interfaces/IsuperAdmin2Step.cairo | 6 +- cairo/src/lib.cairo | 13 +- 16 files changed, 555 insertions(+), 538 deletions(-) rename cairo/src/components/{utils => }/SuperAdmin2Step.cairo (86%) diff --git a/cairo/Scarb.lock b/cairo/Scarb.lock index fc4de3f..eb7dee8 100644 --- a/cairo/Scarb.lock +++ b/cairo/Scarb.lock @@ -2,5 +2,5 @@ version = 1 [[package]] -name = "cairo_starknet" +name = "cairo" version = "0.1.0" diff --git a/cairo/Scarb.toml b/cairo/Scarb.toml index ec24624..4c20759 100644 --- a/cairo/Scarb.toml +++ b/cairo/Scarb.toml @@ -1,16 +1,20 @@ [package] -name = "cairo_starknet" +name = "cairo" version = "0.1.0" edition = "2023_11" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html -[dependencies] - # ... [workspace.dependencies] snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.27.0" } +openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.19.0" } + +[[target.starknet-contract]] + +[dependencies] +starknet = ">=2.5.4" diff --git a/cairo/src/HSTK.cairo b/cairo/src/HSTK.cairo index 2582e58..1358f1e 100644 --- a/cairo/src/HSTK.cairo +++ b/cairo/src/HSTK.cairo @@ -7,11 +7,5 @@ // component!(path: BlackListedComponent, storage: black, event: SupplyEvent); +// } - - - - - - -// } \ No newline at end of file diff --git a/cairo/src/MultiSigL2.cairo b/cairo/src/MultiSigL2.cairo index 99064a9..7311c71 100644 --- a/cairo/src/MultiSigL2.cairo +++ b/cairo/src/MultiSigL2.cairo @@ -2,19 +2,35 @@ pub mod MultiSigL2{ use starknet::{ContractAddress,get_caller_address}; - use cairo_starknet::components::AccessRegistry::AccessRegistryComp; + use cairo::components::AccessRegistry::AccessRegistryComp; + use cairo::component::SuperAdmin2Step::SuperAdminTwoStep; + use openzeppelin::upgrades::interface::IUpgradeable; + use openzeppelin::upgrades::upgradeable::UpgradeableComponent; component!(path:AccessRegistryComp , storage:access_registry , event:AccessRegistryEvents); + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImp; + impl AccessControlInternalImpl = AccessRegistryComp::InternalImpl; + + #[abi(embed_v0)] + impl AccessControlImpl = + AccessRegistryComp::AccessControlImpl; + + #[abi(embed_v0)] + impl SuperAdminTwoStepImpl = + SuperAdminTwoStep::SuperAdminTwoStepImpl; + + // Constants const SIGNER_WINDOW: u64 = 86400; // 24 hours in seconds - const FALLBACK_ADMIN_WINDOW: u64 = 259200; // 72 hours in seconds const APPROVAL_THRESHOLD: u64 = 60; // 60% of signers must approve // Function selectors as constants - const MINT_SELECTOR: felt252 = selector!("add_supported_bridge(ContractAddress)"); - const BURN_SELECTOR: felt252 = selector!("remove_supported_bridge(ContractAddress)"); const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); @@ -33,24 +49,27 @@ pub mod MultiSigL2{ struct Transaction { proposer: ContractAddress, selector: felt252, - params: Array, + params : felt252, proposed_at: u64, first_sign_at: u64, approvals: u64, - state: TransactionState, - is_fallback_admin: bool, + state: TransactionState } #[storage] struct Storage { + token_contract: ContractAddress, transactions: LegacyMap, has_approved: LegacyMap<(u256, ContractAddress), bool>, transaction_exists: LegacyMap, - fallback_admin_functions: LegacyMap, signer_functions: LegacyMap, #[substorage(v0)] - access_registry:AccessRegistryComp::Storage + access_registry:AccessRegistryComp::Storage, + #[substorage(v0)] + upgradeable: UpgradeableComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage } @@ -59,18 +78,23 @@ pub mod MultiSigL2{ enum Event { TransactionProposed: TransactionProposed, TransactionApproved: TransactionApproved, - TransactionRevoked: TransactionRevoked, + SignatoryRevoked: SignatoryRevoked, TransactionExecuted: TransactionExecuted, TransactionExpired: TransactionExpired, TransactionStateChanged: TransactionStateChanged, #[flat] - AccessRegistryEvents::AccessRegistryComp::Events + AccessRegistryEvents:AccessRegistryComp::Events, + #[flat] + UpgradeableEvent: UpgradeableComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event, + } } #[derive(Drop, starknet::Event)] struct TransactionProposed { tx_id: felt252, - proposer: ContractAddress, + proposer:ContractAddress, proposed_at: u64, } @@ -81,7 +105,7 @@ pub mod MultiSigL2{ } #[derive(Drop, starknet::Event)] - struct TransactionRevoked { + struct SignatoryRevoked { tx_id: felt252, revoker: ContractAddress, } @@ -102,18 +126,27 @@ pub mod MultiSigL2{ new_state: TransactionState, } + pub mod Error{ + pub const ZERO_ADDRESS:felt252 = 'CAlldata consist Zero Address'; + } + #[constructor] - fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress, fallback_admin:ContractAddress){ - self.access_registry.initializer(super_admin,fallback_admin); + fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress){ + assert(!token_l2.is_zero() && !super_admin.is_zero(),Error::ZERO_ADDRESS); + self.access_registry.initializer(super_admin); self.token_contract.write(token_l2); } + // Upgradable + #[abi(embed_v0)] + impl UpgradeableImpl of IUpgradeable { + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { + self.accessControl.assert_only_super_admin(); + self.upgradeable._upgrade(new_class_hash); + } + } - - - - - - -} \ No newline at end of file + // impl MultiSigL2Impl< + // TContractState, + // +Has \ No newline at end of file diff --git a/cairo/src/components/AccessRegistry.cairo b/cairo/src/components/AccessRegistry.cairo index 74c60ed..304189a 100644 --- a/cairo/src/components/AccessRegistry.cairo +++ b/cairo/src/components/AccessRegistry.cairo @@ -1,165 +1,144 @@ +//dsdedewded #[starknet::component] -pub mod AccessRegistryComp{ - use starknet::{ContractAddress,get_caller_address}; +mod AccessRegistryComp { + use starknet::get_caller_address; + use starknet::ContractAddress; use cairo::interfaces::IaccessRegistry::IAccessRegistryComponent; - use cairo::components::utils::FallbackAdmin2Step::FallbackAdminTwoStep; - use cairo::components::utils::SuperAdmin2Step::SuperAdminTwoStep; + use cairo::components::SuperAdmin2Step::SuperAdminTwoStep::SuperAdminTwoStepImpl; + use cairo::components::SuperAdmin2Step::SuperAdminTwoStep::InternalImpl; + use cairo::components::SuperAdmin2Step::SuperAdminTwoStep; + use core::num::traits::Zero; #[storage] - struct Storage{ - total_signers:u256, - signers:LegacyMap::, + struct Storage { + total_signers: u256, + signers: LegacyMap:: } + #[event] - #[derive(Drop, starknet::event)] - enum Event{ + #[derive(Drop, PartialEq, starknet::Event)] + pub enum Event { SignerAdded: SignerAdded, SignerRemoved: SignerRemoved, SignerRenounced: SignerRenounced - } + } - #[derive(Drop, starknet::Event)] - pub struct SignerAdded{ + #[derive(Drop, PartialEq, starknet::Event)] + pub struct SignerAdded { #[key] - new_signer:ContractAddress + pub signer: ContractAddress } - #[derive(Drop, starknet::Event)] - pub struct SignerRemoved{ + #[derive(Drop, PartialEq, starknet::Event)] + pub struct SignerRemoved { #[key] - removed_signer: ContractAddress + pub signer: ContractAddress } - #[derive(Drop, starknet::Event)] - pub struct SignerRenounced{ + #[derive(Drop, PartialEq, starknet::Event)] + pub struct SignerRenounced { #[key] - from:ContractAddress, + pub from: ContractAddress, #[key] - to:ContractAddress + pub to: ContractAddress } - pub mod Error{ - pub const ZERO_ADDRESS:felt252 = 'Zero Address'; - pub const SuperAdminIsRestricted:felt252='Super Admin Is Restricted'; - pub const Already_Signer:felt252='Already a Signer'; - pub const SuperAdminCannotRemoved:felt252='Super Admin Cannot Removed'; - pub const NonExistingSigner:felt252='Non Existing Signer'; - + pub mod Error { + pub const ZERO_ADDRESS: felt252 = 'Zero Address'; + pub const SuperAdminIsRestricted: felt252 = 'Super Admin Is Restricted'; + pub const Already_Signer: felt252 = 'Already a Signer'; + pub const SuperAdminCannotRemoved: felt252 = 'Super Admin Cannot Removed'; + pub const NonExistingSigner: felt252 = 'Non Existing Signer'; } - #[embeddable_as(AccessRegistry)] impl AccessRegistyImpl< - TContractState, - +HasComponent, - impl SuperAdminTwoStep:SuperAdminTwoStep::HasComponent, - impl FallbackAdminTwoStep:FallbackAdminTwoStep::HasComponent - > of IAccessRegistryComponent>{ - - fn is_signer(self:@ComponentState,account:ContractAddress)->bool{ + TContractState, + +HasComponent, + impl SuperAdminTwoStepImpl: SuperAdminTwoStep::HasComponent, + +Drop + > of IAccessRegistryComponent> { + fn is_signer(self: @ComponentState, account: ContractAddress) -> bool { self.signers.read(account) } - fn add_signer(ref self: ComponentState, new_signer:ContractAddress){ - + fn add_signer(ref self: ComponentState, new_signer: ContractAddress) { assert(!new_signer.is_zero(), Error::ZERO_ADDRESS); - asser(!self.is_signer(new_signer),Error::Already_Signer); + assert(!self.is_signer(new_signer), Error::Already_Signer); - let super_admin_comp = get_dep_component!(@self,SuperAdminTwoStep); + let super_admin_comp = get_dep_component!(@self, SuperAdminTwoStepImpl); super_admin_comp.assert_only_super_admin(); - self.signers.write(new_signer,true); - self.total_signers.write(self.total_signers.read()+1); - self.emit( - SignerAdded{ - new_signer:existing_owner - }); - + self.signers.write(new_signer, true); + self.total_signers.write(self.total_signers.read() + 1); + self.emit(SignerAdded { signer: new_signer }); } - fn remove_signer(ref self: ComponentState,existing_owner:ContractAddress){ - - assert(!existing_owner.is_zero(), Error::ZERO_ADDRESS); - asser(self.is_signer(existing_owner),Error::Not_A_Signer); + fn remove_signer( + ref self: ComponentState, existing_owner: ContractAddress + ) { + assert(!existing_owner.is_zero(), Error::ZERO_ADDRESS); + assert(self.is_signer(existing_owner), Error::NonExistingSigner); - let super_admin_comp = get_dep_component!(@self,SuperAdminTwoStep); + let super_admin_comp = get_dep_component!(@self, SuperAdminTwoStepImpl); - let super_admin:ContractAddress = super_admin_comp.super_admin(); - assert(existing_owner!=super_admin,Error::SuperAdminCannotRemoved); + let super_admin: ContractAddress = super_admin_comp.super_admin(); + assert(existing_owner != super_admin, Error::SuperAdminCannotRemoved); super_admin_comp.assert_only_super_admin(); + self.signers.write(existing_owner, false); + self.total_signers.write(self.total_signers.read() - 1); - self.signers.write(existing_owner,false); - self.total_signers.write(self.total_signers.read()-1); - - self.emit( - SignerRemoved{ - remove_signer:existing_owner - }); + self.emit(SignerRemoved { signer: existing_owner }); } - fn renounce_signership(ref self: ComponentState,signer:ContractAddress){ - - assert(!signer.is_zero(), Error::ZERO_ADDRESS); //check for zero address - - let caller:ContractAddress = get_caller_address(); - assert(self.is_signer(caller),Error::Not_A_Signer); //only be calleable by signer - assert(!self.is_signer(signer),Error::Already_Signer); //new signer cannot be existing signer - - let super_admin_comp = get_dep_component!(@self,SuperAdminTwoStep); - let super_admin:ContractAddress = super_admin_comp.super_admin(); - assert(existing_owner!=super_admin,Error::SuperAdminCannotRemoved); //signer cannot be remove + fn renounce_signership(ref self: ComponentState, signer: ContractAddress) { + assert(!signer.is_zero(), Error::ZERO_ADDRESS); //check for zero address + + let caller: ContractAddress = get_caller_address(); + assert(self.is_signer(caller), Error::NonExistingSigner); //only be calleable by signer + assert( + !self.is_signer(signer), Error::Already_Signer + ); //new signer cannot be existing signer + + let super_admin_comp = get_dep_component!(@self, SuperAdminTwoStepImpl); + let super_admin: ContractAddress = super_admin_comp.super_admin(); + assert(caller != super_admin, Error::SuperAdminCannotRemoved); //signer cannot be remove // check it needs to be existing owner - _renounce_signership(caller,signer); + self._renounce_signership(caller, signer); } - fn accept_super_adminship(ref self:ComponentState){ - - let caller:ContractAddress = get_caller_address(); - let super_admin_comp = get_dep_component!(ref self, SuperAdminTwoStep); - let super_admin:ContractAddress = super_admin_comp.super_admin(); + + fn accept_super_adminship(ref self: ComponentState) { + let caller: ContractAddress = get_caller_address(); + let mut super_admin_comp = get_dep_component_mut!(ref self, SuperAdminTwoStepImpl); + let super_admin: ContractAddress = super_admin_comp.super_admin(); super_admin_comp._accept_super_adminship(); - self._renounce_signership(caller,super_admin); + self._renounce_signership(caller, super_admin); } + } - #[generate_trait] - pub impl InternalImpl< - TContractState, +HasComponent - > of InternalTrait - - fn initializer(ref self: ComponentState,super_admin:ContractAddress, fallback_admin:ContractAddress){ - let super_admin_comp = get_dep_component!(ref self,SuperAdminTwoStep); - let fallback_admin_comp = get_dep_component!(ref self,FallbackAdminTwoStep); - super_admin_comp.initializer(super_admin); - fallback_admin_comp.initializer(fallback_admin); - self.total_signers.write(1); - self.signers.write(super_admin,true); - } - - fn _renounce_signership(ref self:ComponentState,from:ContractAddress, to:ContractAddress){ - - self.signers.write(from,false); - self.signers.write(to,true); - - self.emit( - SignerRenounced{ - from:from, - to:to - }) - - } + #[generate_trait] + impl InternalImp< + TContractState, + +HasComponent, + impl SuperAdminTwoStepImpl: SuperAdminTwoStep::HasComponent, + +Drop + > of InternalTrait { + fn initializer(ref self: ComponentState, super_admin: ContractAddress) { + let mut super_admin_comp = get_dep_component_mut!(ref self, SuperAdminTwoStepImpl); + super_admin_comp.initializer(super_admin); + self.total_signers.write(1); + self.signers.write(super_admin, true); } + fn _renounce_signership( + ref self: ComponentState, _from: ContractAddress, _to: ContractAddress + ) { + self.signers.write(_from, false); + self.signers.write(_to, true); - - - - - - - - - - - -} \ No newline at end of file + self.emit(SignerRenounced { from: _from, to: _to }); + } + } +} diff --git a/cairo/src/components/BlackListed.cairo b/cairo/src/components/BlackListed.cairo index 69c1ad0..997a9a3 100644 --- a/cairo/src/components/BlackListed.cairo +++ b/cairo/src/components/BlackListed.cairo @@ -1,17 +1,20 @@ -#[starknet::component] -pub mod BlackListedComponent { - use starknet::{ContractAddress,get_caller_address}; - use core::panic_with_felt252; +use starknet::{ContractAddress, get_caller_address}; +use core::traits::Into; +use core::option::OptionTrait; +#[starknet::component] +mod BlackListedComp { + use core::num::traits::zero::Zero; use cairo::interfaces::IblackListed::IBlackListedComponent; + use starknet::{ContractAddress, get_caller_address}; + use core::traits::Into; #[storage] struct Storage { - blackListedAccount: LegacyMap::, - multiSig: ContractAddress + blacklisted_account: LegacyMap, + multi_sig: ContractAddress, } - // Events #[event] #[derive(Drop, starknet::Event)] enum Event { @@ -20,57 +23,63 @@ pub mod BlackListedComponent { } #[derive(Drop, starknet::Event)] - pub struct NewAccountBlackListed{ + struct NewAccountBlackListed { #[key] - blackListed_account:ContractAddress + blacklisted_account: ContractAddress } - #[derive(Drop,starknet::Event)] - pub struct RemovedAccountBlackListed{ + #[derive(Drop, starknet::Event)] + struct RemovedAccountBlackListed { #[key] - removed_Account: ContractAddress + removed_account: ContractAddress } - pub mod Error{ - pub const AccountBlackListed:felt252 ='Account is BlackListed'; - pub const RestrictedToMultiSig:felt252 ='Restricted To MultiSig Contract'; + mod errors { + pub const ACCOUNT_BLACKLISTED: felt252 = 'Account is BlackListed'; + pub const RESTRICTED_TO_MULTISIG: felt252 = 'Restricted To MultiSig Contract'; + pub const ZERO_ADDRESS: felt252 = 'Calldata consist Zero Address'; } - #[generate_trait] - impl InternalFunctionBlackListed> - of InternalFunctionBlackListedTraits{ - fn initializer(ref self: ComponentState , multiSig: ContractAddress){ - self.multiSig.write(multiSig); + #[embeddable_as(BlackListed)] + impl BlackListedImpl< + TContractState, +HasComponent + > of IBlackListedComponent> { + fn is_blacklisted_account( + self: @ComponentState, account: ContractAddress + ) -> bool { + self.blacklisted_account.read(account) } - - fn _only_multiSig(self:@ComponentState){ - assert(get_caller_address() != self.multiSig.read(),Error::RestrictedToMultiSig); + fn blacklist_account(ref self: ComponentState, account: ContractAddress) { + self._only_multi_sig(); + self.blacklisted_account.write(account, true); + self.emit(NewAccountBlackListed { blacklisted_account: account }); } - fn _not_blackListed(self:@ComponentState,check:ContractAddress){ - let flag: bool = self.blackListedAccount.read(check); - assert(flag,Error::AccountBlackListed); + fn remove_blacklisted_account( + ref self: ComponentState, account: ContractAddress + ) { + self._only_multi_sig(); + self.blacklisted_account.write(account, false); + self.emit(RemovedAccountBlackListed { removed_account: account }); } + } - fn blackList_account(ref self : ComponentState, account:ContractAddress){ - self._only_multiSig(); - self.blackListedAccount.write(account,true); - self.emit(NewAccountBlackListed{ - blackListed_account:account - }); + #[generate_trait] + impl InternalFunctions< + TContractState, +HasComponent + > of InternalFunctionsTrait { + fn initializer(ref self: ComponentState, multi_sig: ContractAddress) { + assert(multi_sig.is_zero(), errors::ZERO_ADDRESS); + self.multi_sig.write(multi_sig); } - fn remove_blackListed_account(ref self: ComponentState, account : ContractAddress){ - self._only_multiSig(); - self.blackListedAccount.write(account,false); - self.emit(RemovedAccountBlackListed{ - removed_Account:account - }); + fn _only_multi_sig(self: @ComponentState) { + assert(get_caller_address() == self.multi_sig.read(), errors::RESTRICTED_TO_MULTISIG); } - fn is_blackListed_account(self :@ComponentState, account:ContractAddress)-> bool { - return self.blackListedAccount.read(account); + fn _not_blacklisted(self: @ComponentState, check: ContractAddress) { + let flag: bool = self.blacklisted_account.read(check); + assert(!flag, errors::ACCOUNT_BLACKLISTED); } - } -} \ No newline at end of file +} diff --git a/cairo/src/components/Pausable.cairo b/cairo/src/components/Pausable.cairo index 8576953..3d3c9ee 100644 --- a/cairo/src/components/Pausable.cairo +++ b/cairo/src/components/Pausable.cairo @@ -1,148 +1,285 @@ -// // Define the pause states using an enum -// #[starknet::component] -// pub mod Pausable { -// use cairo_starknet::helpers::constants; -// use cairo_starknet::interfaces::Ipausable::IPausable; +// // // Define the pause states using an enum +// // #[starknet::component] +// // pub mod Pausable { +// // use cairo_starknet::helpers::constants; +// // use cairo_starknet::interfaces::Ipausable::IPausable; + +// // #[derive(Drop, Copy, Serde)] +// // pub enum PauseState { +// // Active, +// // PartialPause, +// // FullPause +// // } + +// // #[storage] +// // struct Storage { +// // current_state: PauseState +// // } + +// // #[event] +// // #[derive(Drop, starknet::Event)] +// // enum Event { +// // PauseStateChanged: PauseStateChanged, +// // } + +// // #[derive(Drop, starknet::Event)] +// // struct PauseStateChanged { +// // new_state: PauseState, +// // } + +// // #[derive(Drop, PartialEq)] +// // enum PausableError { +// // EnforcedPause, +// // EnforcedPartialPause, +// // InvalidStateChange, +// // } + +// // fn panic_with_felt252(err: felt252) { +// // core::panic_with_felt252(err) +// // } + +// // impl PausableErrorIntoFelt252 of Into { +// // fn into(self: PausableError) -> felt252 { +// // match self { +// // PausableError::EnforcedPause => 'Contract is fully paused', +// // PausableError::EnforcedPartialPause => 'Contract is partially paused', +// // PausableError::InvalidStateChange => 'Invalid state change' +// // } +// // } +// // } + +// // #[embeddable_as(Pausable)] +// // impl PausableImpl< +// // TContractState, +// // impl TContractStateDestruct: Drop, +// // impl TContractStateComponent: HasComponent +// // > of IPausable> { +// // fn get_current_state(self: @ComponentState) -> PauseState { +// // self.current_state.read() +// // } + +// // fn is_active(self: @ComponentState) -> bool { +// // match self.current_state.read() { +// // PauseState::Active => true, +// // _ => false +// // } +// // } + +// // fn is_partial_paused(self: @ComponentState) -> bool { +// // match self.current_state.read() { +// // PauseState::PartialPause => true, +// // _ => false +// // } +// // } + +// // fn is_full_paused(self: @ComponentState) -> bool { +// // match self.current_state.read() { +// // PauseState::FullPause => true, +// // _ => false +// // } +// // } +// // } + +// // #[generate_trait] +// // impl InternalFunctions< +// // TContractState, +// // impl TContractStateDestruct: Drop, +// // impl TContractStateComponent: HasComponent +// // > of InternalFunctionsTrait { +// // fn initializer(ref self: ComponentState) { +// // self.current_state.write(PauseState::Active); +// // } + +// // fn _require_active(self: @ComponentState) { +// // let current_state = self.current_state.read(); +// // match current_state { +// // PauseState::Active => {}, +// // PauseState::PartialPause => { +// // panic_with_felt252(PausableError::EnforcedPartialPause.into()) +// // }, +// // PauseState::FullPause => { +// // panic_with_felt252(PausableError::EnforcedPause.into()) +// // } +// // } +// // } + +// // fn _require_active_or_partial(self: @ComponentState) { +// // let current_state = self.current_state.read(); +// // match current_state { +// // PauseState::Active => {}, +// // PauseState::PartialPause => {}, +// // PauseState::FullPause => { +// // panic_with_felt252(PausableError::EnforcedPause.into()) +// // } +// // } +// // } + +// // fn _update_operational_state( +// // ref self: ComponentState, +// // new_state: PauseState +// // ) { +// // self.current_state.write(new_state); + +// // // Emit state change event +// // self.emit(Event::PauseStateChanged( +// // PauseStateChanged { new_state } +// // )); +// // } +// // } +// // } + +// // #[starknet::component] +// // pub mod Pausable { +// // use starknet::ContractAddress; +// // use cairo_starknet::helpers::constants; +// // use cairo_starknet::interfaces::Ipausable::IPausable; + +// // #[derive(Drop, Copy, Serde)] +// // pub enum PauseState { +// // Active, +// // PartialPause, +// // FullPause +// // } + +// // #[storage] +// // struct Storage { +// // current_state: PauseState +// // } + +// // #[event] +// // #[derive(Drop, starknet::Event)] +// // enum Event { +// // PauseStateChanged: PauseStateChanged, +// // } + +// // #[derive(Drop, starknet::Event)] +// // struct PauseStateChanged { +// // new_state: PauseState, +// // } + +// // #[derive(Drop, PartialEq)] +// // enum PausableError { +// // EnforcedPause, +// // EnforcedPartialPause, +// // InvalidStateChange, +// // } + +// // fn panic_with_felt252(err: felt252) { +// // core::panic_with_felt252(err) +// // } + +// // impl PausableErrorIntoFelt252 of Into { +// // fn into(self: PausableError) -> felt252 { +// // match self { +// // PausableError::EnforcedPause => 'Contract is fully paused', +// // PausableError::EnforcedPartialPause => 'Contract is partially paused', +// // PausableError::InvalidStateChange => 'Invalid state change' +// // } +// // } +// // } + +// // #[embeddable_as(Pausable)] +// // impl PausableImpl< +// // TContractState, +// // impl TContractStateDestruct: Drop, +// // impl TContractStateComponent: HasComponent +// // > of IPausable> { +// // fn get_current_state(self: @ComponentState) -> PauseState { +// // let state = self.current_state.read(); +// // state +// // } + +// // fn is_active(self: @ComponentState) -> bool { +// // match self.get_current_state() { +// // PauseState::Active => true, +// // _ => false +// // } +// // } + +// // fn is_partial_paused(self: @ComponentState) -> bool { +// // match self.get_current_state() { +// // PauseState::PartialPause => true, +// // _ => false +// // } +// // } + +// // fn is_full_paused(self: @ComponentState) -> bool { +// // match self.get_current_state() { +// // PauseState::FullPause => true, +// // _ => false +// // } +// // } +// // } + +// // #[generate_trait] +// // impl InternalFunctions< +// // TContractState, +// // impl TContractStateDestruct: Drop, +// // impl TContractStateComponent: HasComponent +// // > of InternalFunctionsTrait { +// // fn initializer(ref self: ComponentState) { +// // self.current_state.write(PauseState::Active); +// // } + +// // fn _require_active(self: @ComponentState) { +// // match self.get_current_state() { +// // PauseState::Active => {}, +// // PauseState::PartialPause => { +// // panic_with_felt252(PausableError::EnforcedPartialPause.into()) +// // }, +// // PauseState::FullPause => { +// // panic_with_felt252(PausableError::EnforcedPause.into()) +// // } +// // } +// // } + +// // fn _require_active_or_partial(self: @ComponentState) { +// // match self.get_current_state() { +// // PauseState::Active => {}, +// // PauseState::PartialPause => {}, +// // PauseState::FullPause => { +// // panic_with_felt252(PausableError::EnforcedPause.into()) +// // } +// // } +// // } + +// // fn _update_operational_state( +// // ref self: ComponentState, +// // new_state: PauseState +// // ) { +// // self.current_state.write(new_state); + +// // // Emit state change event +// // self.emit(Event::PauseStateChanged( +// // PauseStateChanged { new_state } +// // )); +// // } +// // } +// // } + +// use starknet::ContractAddress; +// use core::starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; + +// #[starknet::interface] +// trait IPausable { +// fn get_current_state(self: @TContractState) -> PauseState; +// fn is_active(self: @TContractState) -> bool; +// fn is_partial_paused(self: @TContractState) -> bool; +// fn is_full_paused(self: @TContractState) -> bool; +// } -// #[derive(Drop, Copy, Serde)] -// pub enum PauseState { +// #[derive(Drop, Copy, Serde)] +// pub enum PauseState { // Active, // PartialPause, // FullPause -// } - -// #[storage] -// struct Storage { -// current_state: PauseState -// } - -// #[event] -// #[derive(Drop, starknet::Event)] -// enum Event { -// PauseStateChanged: PauseStateChanged, -// } - -// #[derive(Drop, starknet::Event)] -// struct PauseStateChanged { -// new_state: PauseState, -// } - -// #[derive(Drop, PartialEq)] -// enum PausableError { -// EnforcedPause, -// EnforcedPartialPause, -// InvalidStateChange, -// } - -// fn panic_with_felt252(err: felt252) { -// core::panic_with_felt252(err) -// } - -// impl PausableErrorIntoFelt252 of Into { -// fn into(self: PausableError) -> felt252 { -// match self { -// PausableError::EnforcedPause => 'Contract is fully paused', -// PausableError::EnforcedPartialPause => 'Contract is partially paused', -// PausableError::InvalidStateChange => 'Invalid state change' -// } -// } -// } - -// #[embeddable_as(Pausable)] -// impl PausableImpl< -// TContractState, -// impl TContractStateDestruct: Drop, -// impl TContractStateComponent: HasComponent -// > of IPausable> { -// fn get_current_state(self: @ComponentState) -> PauseState { -// self.current_state.read() -// } - -// fn is_active(self: @ComponentState) -> bool { -// match self.current_state.read() { -// PauseState::Active => true, -// _ => false -// } -// } - -// fn is_partial_paused(self: @ComponentState) -> bool { -// match self.current_state.read() { -// PauseState::PartialPause => true, -// _ => false -// } -// } - -// fn is_full_paused(self: @ComponentState) -> bool { -// match self.current_state.read() { -// PauseState::FullPause => true, -// _ => false -// } -// } -// } - -// #[generate_trait] -// impl InternalFunctions< -// TContractState, -// impl TContractStateDestruct: Drop, -// impl TContractStateComponent: HasComponent -// > of InternalFunctionsTrait { -// fn initializer(ref self: ComponentState) { -// self.current_state.write(PauseState::Active); -// } - -// fn _require_active(self: @ComponentState) { -// let current_state = self.current_state.read(); -// match current_state { -// PauseState::Active => {}, -// PauseState::PartialPause => { -// panic_with_felt252(PausableError::EnforcedPartialPause.into()) -// }, -// PauseState::FullPause => { -// panic_with_felt252(PausableError::EnforcedPause.into()) -// } -// } -// } - -// fn _require_active_or_partial(self: @ComponentState) { -// let current_state = self.current_state.read(); -// match current_state { -// PauseState::Active => {}, -// PauseState::PartialPause => {}, -// PauseState::FullPause => { -// panic_with_felt252(PausableError::EnforcedPause.into()) -// } -// } -// } - -// fn _update_operational_state( -// ref self: ComponentState, -// new_state: PauseState -// ) { -// self.current_state.write(new_state); - -// // Emit state change event -// self.emit(Event::PauseStateChanged( -// PauseStateChanged { new_state } -// )); -// } -// } // } - - // #[starknet::component] // pub mod Pausable { +// use super::{PauseState, IPausable}; // use starknet::ContractAddress; -// use cairo_starknet::helpers::constants; -// use cairo_starknet::interfaces::Ipausable::IPausable; - - -// #[derive(Drop, Copy, Serde)] -// pub enum PauseState { -// Active, -// PartialPause, -// FullPause -// } +// use core::starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; // #[storage] // struct Storage { @@ -188,8 +325,8 @@ // impl TContractStateComponent: HasComponent // > of IPausable> { // fn get_current_state(self: @ComponentState) -> PauseState { -// let state = self.current_state.read(); -// state +// let current_state = StorageMemberAccessTrait::::read(self.current_state.address()); +// current_state // } // fn is_active(self: @ComponentState) -> bool { @@ -221,7 +358,10 @@ // impl TContractStateComponent: HasComponent // > of InternalFunctionsTrait { // fn initializer(ref self: ComponentState) { -// self.current_state.write(PauseState::Active); +// StorageMemberAccessTrait::::write( +// self.current_state.address(), +// PauseState::Active +// ); // } // fn _require_active(self: @ComponentState) { @@ -246,151 +386,5 @@ // } // } -// fn _update_operational_state( -// ref self: ComponentState, -// new_state: PauseState -// ) { -// self.current_state.write(new_state); - -// // Emit state change event -// self.emit(Event::PauseStateChanged( -// PauseStateChanged { new_state } -// )); -// } -// } -// } - - - - +// fn _update_operational_ -use starknet::ContractAddress; -use core::starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; - -#[starknet::interface] -trait IPausable { - fn get_current_state(self: @TContractState) -> PauseState; - fn is_active(self: @TContractState) -> bool; - fn is_partial_paused(self: @TContractState) -> bool; - fn is_full_paused(self: @TContractState) -> bool; -} - -#[derive(Drop, Copy, Serde)] -pub enum PauseState { - Active, - PartialPause, - FullPause -} - -#[starknet::component] -pub mod Pausable { - use super::{PauseState, IPausable}; - use starknet::ContractAddress; - use core::starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; - - #[storage] - struct Storage { - current_state: PauseState - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - PauseStateChanged: PauseStateChanged, - } - - #[derive(Drop, starknet::Event)] - struct PauseStateChanged { - new_state: PauseState, - } - - #[derive(Drop, PartialEq)] - enum PausableError { - EnforcedPause, - EnforcedPartialPause, - InvalidStateChange, - } - - fn panic_with_felt252(err: felt252) { - core::panic_with_felt252(err) - } - - impl PausableErrorIntoFelt252 of Into { - fn into(self: PausableError) -> felt252 { - match self { - PausableError::EnforcedPause => 'Contract is fully paused', - PausableError::EnforcedPartialPause => 'Contract is partially paused', - PausableError::InvalidStateChange => 'Invalid state change' - } - } - } - - #[embeddable_as(Pausable)] - impl PausableImpl< - TContractState, - impl TContractStateDestruct: Drop, - impl TContractStateComponent: HasComponent - > of IPausable> { - fn get_current_state(self: @ComponentState) -> PauseState { - let current_state = StorageMemberAccessTrait::::read(self.current_state.address()); - current_state - } - - fn is_active(self: @ComponentState) -> bool { - match self.get_current_state() { - PauseState::Active => true, - _ => false - } - } - - fn is_partial_paused(self: @ComponentState) -> bool { - match self.get_current_state() { - PauseState::PartialPause => true, - _ => false - } - } - - fn is_full_paused(self: @ComponentState) -> bool { - match self.get_current_state() { - PauseState::FullPause => true, - _ => false - } - } - } - - #[generate_trait] - impl InternalFunctions< - TContractState, - impl TContractStateDestruct: Drop, - impl TContractStateComponent: HasComponent - > of InternalFunctionsTrait { - fn initializer(ref self: ComponentState) { - StorageMemberAccessTrait::::write( - self.current_state.address(), - PauseState::Active - ); - } - - fn _require_active(self: @ComponentState) { - match self.get_current_state() { - PauseState::Active => {}, - PauseState::PartialPause => { - panic_with_felt252(PausableError::EnforcedPartialPause.into()) - }, - PauseState::FullPause => { - panic_with_felt252(PausableError::EnforcedPause.into()) - } - } - } - - fn _require_active_or_partial(self: @ComponentState) { - match self.get_current_state() { - PauseState::Active => {}, - PauseState::PartialPause => {}, - PauseState::FullPause => { - panic_with_felt252(PausableError::EnforcedPause.into()) - } - } - } - - fn _update_operational_ \ No newline at end of file diff --git a/cairo/src/components/utils/SuperAdmin2Step.cairo b/cairo/src/components/SuperAdmin2Step.cairo similarity index 86% rename from cairo/src/components/utils/SuperAdmin2Step.cairo rename to cairo/src/components/SuperAdmin2Step.cairo index ae4f9f5..ad20934 100644 --- a/cairo/src/components/utils/SuperAdmin2Step.cairo +++ b/cairo/src/components/SuperAdmin2Step.cairo @@ -21,7 +21,7 @@ pub mod SuperAdminTwoStep { use cairo::interfaces::IsuperAdmin2Step; use starknet::ContractAddress; - use starknet::{get_caller_address,get_block_timestamp}; + use starknet::{get_caller_address, get_block_timestamp}; #[storage] pub struct Storage { @@ -51,7 +51,6 @@ pub mod SuperAdminTwoStep { pub previous_super_admin: ContractAddress, #[key] pub new_super_admin: ContractAddress, - } pub mod Errors { @@ -63,10 +62,9 @@ pub mod SuperAdminTwoStep { } /// Adds support for two step super_adminship transfer. - #[embeddable_as(SuperAdminTwoStepImpl)] - impl SuperAdminTwoStep< - TContractState, - +HasComponent + #[embeddable_as(SuperAdminTwoStep)] + pub impl SuperAdminTwoStepImpl< + TContractState, +HasComponent > of IsuperAdmin2Step::ISuperAdminTwoStep> { /// Returns the address of the current super_admin. fn super_admin(self: @ComponentState) -> ContractAddress { @@ -77,9 +75,9 @@ pub mod SuperAdminTwoStep { fn pending_super_admin(self: @ComponentState) -> ContractAddress { self.pending_admin.read() } - + //Returns the handover expiry of the pending super_admin - fn super_handover_expires_at(self:@ComponentState ) -> u64 { + fn super_handover_expires_at(self: @ComponentState) -> u64 { self.handover_expires.read() } @@ -99,16 +97,14 @@ pub mod SuperAdminTwoStep { } /// Returns the time for which handover is valid for pending super_admin. - fn super_admin_ownership_valid_for(self:@ComponentState)->u64{ - 72*3600 + fn super_admin_ownership_valid_for(self: @ComponentState) -> u64 { + 72 * 3600 } - } #[generate_trait] pub impl InternalImpl< - TContractState, - +HasComponent + TContractState, +HasComponent > of InternalTrait { /// Sets the contract's initial super_admin. /// @@ -137,9 +133,9 @@ pub mod SuperAdminTwoStep { fn _accept_super_adminship(ref self: ComponentState) { let caller = get_caller_address(); let pending_super_admin = self.pending_admin.read(); - let super_adminship_expires_at:u64 = self.handover_expires.read(); + let super_adminship_expires_at: u64 = self.handover_expires.read(); assert(caller == pending_super_admin, Errors::NOT_PENDING_OWNER); - assert(get_block_timestamp()<= super_adminship_expires_at,Errors::HANDOVER_EXPIRED); + assert(get_block_timestamp() <= super_adminship_expires_at, Errors::HANDOVER_EXPIRED); self._transfer_super_adminship(pending_super_admin); } @@ -159,7 +155,9 @@ pub mod SuperAdminTwoStep { self.super_admin.write(new_super_admin); self .emit( - SuperOwnershipTransferred { previous_super_admin: previous_super_admin, new_super_admin: new_super_admin } + SuperOwnershipTransferred { + previous_super_admin: previous_super_admin, new_super_admin: new_super_admin + } ); } @@ -168,10 +166,13 @@ pub mod SuperAdminTwoStep { /// Internal function without access restriction. /// /// Emits an `OwnershipTransferStarted` event. - fn _propose_super_admin(ref self: ComponentState, new_super_admin: ContractAddress) { + fn _propose_super_admin( + ref self: ComponentState, new_super_admin: ContractAddress + ) { let previous_super_admin = self.super_admin.read(); self.pending_admin.write(new_super_admin); - let super_adminship_expires_at = get_block_timestamp() + self.super_admin_ownership_valid_for(); + let super_adminship_expires_at = get_block_timestamp() + + self.super_admin_ownership_valid_for(); self.handover_expires.write(super_adminship_expires_at); self .emit( @@ -181,4 +182,4 @@ pub mod SuperAdminTwoStep { ); } } -} \ No newline at end of file +} diff --git a/cairo/src/components/utils/FallbackAdmin2Step.cairo b/cairo/src/components/utils/FallbackAdmin2Step.cairo index c4135b0..ac3a7a8 100644 --- a/cairo/src/components/utils/FallbackAdmin2Step.cairo +++ b/cairo/src/components/utils/FallbackAdmin2Step.cairo @@ -21,7 +21,7 @@ pub mod FallbackAdminTwoStep { use cairo::interfaces::IfallbackAdmin2Step; use starknet::ContractAddress; - use starknet::{get_caller_address,get_block_timestamp}; + use starknet::{get_caller_address, get_block_timestamp}; #[storage] pub struct Storage { @@ -51,7 +51,6 @@ pub mod FallbackAdminTwoStep { pub previous_fallback_admin: ContractAddress, #[key] pub new_fallback_admin: ContractAddress, - } pub mod Errors { @@ -76,9 +75,9 @@ pub mod FallbackAdminTwoStep { fn pending_fallback_admin(self: @ComponentState) -> ContractAddress { self.pending_admin.read() } - + //Returns the handover expiry of the pending fallback_admin - fn fallback_handover_expires_at(self:@ComponentState ) -> u64 { + fn fallback_handover_expires_at(self: @ComponentState) -> u64 { self.handover_expires.read() } @@ -93,9 +92,11 @@ pub mod FallbackAdminTwoStep { fn accept_fallback_adminship(ref self: ComponentState) { let caller = get_caller_address(); let pending_fallback_admin = self.pending_admin.read(); - let fallback_adminship_expires_at:u64 = self.handover_expires.read(); + let fallback_adminship_expires_at: u64 = self.handover_expires.read(); assert(caller == pending_fallback_admin, Errors::NOT_PENDING_OWNER); - assert(get_block_timestamp()<= fallback_adminship_expires_at,Errors::HANDOVER_EXPIRED); + assert( + get_block_timestamp() <= fallback_adminship_expires_at, Errors::HANDOVER_EXPIRED + ); self._transfer_fallback_adminship(pending_fallback_admin); } @@ -114,10 +115,9 @@ pub mod FallbackAdminTwoStep { } /// Returns the time for which handover is valid for pending fallback_admin. - fn fallback_admin_ownership_valid_for(self:@ComponentState)->u64{ - 72*3600 + fn fallback_admin_ownership_valid_for(self: @ComponentState) -> u64 { + 72 * 3600 } - } #[generate_trait] @@ -156,7 +156,10 @@ pub mod FallbackAdminTwoStep { self.fallback_admin.write(new_fallback_admin); self .emit( - FallbackOwnershipTransferred{ previous_fallback_admin: previous_fallback_admin, new_fallback_admin: new_fallback_admin } + FallbackOwnershipTransferred { + previous_fallback_admin: previous_fallback_admin, + new_fallback_admin: new_fallback_admin + } ); } @@ -165,17 +168,21 @@ pub mod FallbackAdminTwoStep { /// Internal function without access restriction. /// /// Emits an `OwnershipTransferStarted` event. - fn _propose_fallback_admin(ref self: ComponentState, new_fallback_admin: ContractAddress) { + fn _propose_fallback_admin( + ref self: ComponentState, new_fallback_admin: ContractAddress + ) { let previous_fallback_admin = self.fallback_admin.read(); self.pending_admin.write(new_fallback_admin); - let fallback_adminship_expires_at = get_block_timestamp() + self.fallback_admin_ownership_valid_for(); + let fallback_adminship_expires_at = get_block_timestamp() + + self.fallback_admin_ownership_valid_for(); self.handover_expires.write(fallback_adminship_expires_at); self .emit( FallbackOwnershipTransferStarted { - previous_fallback_admin: previous_fallback_admin, new_fallback_admin: new_fallback_admin + previous_fallback_admin: previous_fallback_admin, + new_fallback_admin: new_fallback_admin } ); } } -} \ No newline at end of file +} diff --git a/cairo/src/helpers/constants.cairo b/cairo/src/helpers/constants.cairo index a0df7f4..75692b8 100644 --- a/cairo/src/helpers/constants.cairo +++ b/cairo/src/helpers/constants.cairo @@ -1,4 +1,3 @@ - pub const Active: felt252 = 0; pub const PartialPause: felt252 = 1; pub const FullPause: felt252 = 2; diff --git a/cairo/src/interfaces/IaccessRegistry.cairo b/cairo/src/interfaces/IaccessRegistry.cairo index ba79627..a700fb7 100644 --- a/cairo/src/interfaces/IaccessRegistry.cairo +++ b/cairo/src/interfaces/IaccessRegistry.cairo @@ -1,9 +1,9 @@ use starknet::ContractAddress; #[starknet::interface] pub trait IAccessRegistryComponent { - fn add_signer(ref self:TContractState, new_signer:ContractAddress); - fn remove_signer(ref self: TContractState,existing_owner: ContractAddress); - fn renounce_signership(ref self: TContractState,signer: ContractAddress); - fn is_signer(self :@TContractState,account:ContractAddress)->bool; - fn accept_super_adminship(ref self:TContractState); -} \ No newline at end of file + fn add_signer(ref self: TContractState, new_signer: ContractAddress); + fn remove_signer(ref self: TContractState, existing_owner: ContractAddress); + fn renounce_signership(ref self: TContractState, signer: ContractAddress); + fn is_signer(self: @TContractState, account: ContractAddress) -> bool; + fn accept_super_adminship(ref self: TContractState); +} diff --git a/cairo/src/interfaces/IblackListed.cairo b/cairo/src/interfaces/IblackListed.cairo index fcd6c7e..3f849ac 100644 --- a/cairo/src/interfaces/IblackListed.cairo +++ b/cairo/src/interfaces/IblackListed.cairo @@ -1,7 +1,7 @@ use starknet::ContractAddress; #[starknet::interface] pub trait IBlackListedComponent { - fn blackList_account(ref self:TContractState, account:ContractAddress); - fn remove_blackListed_account(ref self: TContractState,account: ContractAddress); - fn is_blackListed_account(self: @TContractState) -> bool; -} \ No newline at end of file + fn is_blacklisted_account(self: @TContractState, account: ContractAddress) -> bool; + fn blacklist_account(ref self: TContractState, account: ContractAddress); + fn remove_blacklisted_account(ref self: TContractState, account: ContractAddress); +} diff --git a/cairo/src/interfaces/IfallbackAdmin2Step.cairo b/cairo/src/interfaces/IfallbackAdmin2Step.cairo index faa0ff4..9b2ff64 100644 --- a/cairo/src/interfaces/IfallbackAdmin2Step.cairo +++ b/cairo/src/interfaces/IfallbackAdmin2Step.cairo @@ -8,6 +8,6 @@ pub trait IFallbackAdminTwoStep { fn pending_fallback_admin(self: @TState) -> ContractAddress; fn accept_fallback_adminship(ref self: TState); fn transfer_fallback_adminship(ref self: TState, new_fallback_admin: ContractAddress); - fn fallback_admin_ownership_valid_for(self:@TState)->u64; - fn fallback_handover_expires_at(self: @TState)->u64; -} \ No newline at end of file + fn fallback_admin_ownership_valid_for(self: @TState) -> u64; + fn fallback_handover_expires_at(self: @TState) -> u64; +} diff --git a/cairo/src/interfaces/Ipausable.cairo b/cairo/src/interfaces/Ipausable.cairo index 0a92e3d..4bb5be7 100644 --- a/cairo/src/interfaces/Ipausable.cairo +++ b/cairo/src/interfaces/Ipausable.cairo @@ -1,4 +1,4 @@ -use cairo_starknet::helpers::constants; +use cairo::helpers::constants; // Define the pause states using an enum #[derive(Drop, Copy, Serde)] pub enum PauseState { @@ -8,7 +8,7 @@ pub enum PauseState { } #[starknet::interface] -pub trait IPausable{ +pub trait IPausable { fn get_current_state(self: @T1) -> PauseState; fn is_active(self: @T1) -> bool; fn is_partial_paused(self: @T1) -> bool; @@ -21,4 +21,4 @@ fn get_state_felt(state: PauseState) -> felt252 { PauseState::PartialPause => constants::PartialPause, PauseState::FullPause => constants::FullPause } -} \ No newline at end of file +} diff --git a/cairo/src/interfaces/IsuperAdmin2Step.cairo b/cairo/src/interfaces/IsuperAdmin2Step.cairo index d7535b1..750ee23 100644 --- a/cairo/src/interfaces/IsuperAdmin2Step.cairo +++ b/cairo/src/interfaces/IsuperAdmin2Step.cairo @@ -7,6 +7,6 @@ pub trait ISuperAdminTwoStep { fn super_admin(self: @TState) -> ContractAddress; fn pending_super_admin(self: @TState) -> ContractAddress; fn transfer_super_adminship(ref self: TState, new_super_admin: ContractAddress); - fn super_admin_ownership_valid_for(self:@TState)->u64; - fn super_handover_expires_at(self: @TState)->u64; -} \ No newline at end of file + fn super_admin_ownership_valid_for(self: @TState) -> u64; + fn super_handover_expires_at(self: @TState) -> u64; +} diff --git a/cairo/src/lib.cairo b/cairo/src/lib.cairo index b1ab5b5..d175855 100644 --- a/cairo/src/lib.cairo +++ b/cairo/src/lib.cairo @@ -6,15 +6,12 @@ // mod BlackListed; // mod Pausable; // } -pub mod components{ +pub mod components { pub mod Pausable; pub mod BlackListed; pub mod AccessRegistry; - pub mod utils{ - pub mod SuperAdmin2Step; - pub mod FallbackAdmin2Step; - } - } + pub mod SuperAdmin2Step; +} pub mod interfaces { pub mod Ipausable; pub mod IblackListed; @@ -26,5 +23,5 @@ pub mod helpers { pub mod constants; } -pub mod HSTK; -pub mod MultiSigl2; \ No newline at end of file +// pub mod HSTK; +pub mod MultiSigl2; From a0f1818b6fbae88962540142e63a4f63e18ba45b Mon Sep 17 00:00:00 2001 From: Saurabh Date: Wed, 13 Nov 2024 23:38:43 +0530 Subject: [PATCH 3/8] [FEAT] added support for multisig[IN_PROGRESS] --- cairo/.tool-versions | 1 + cairo/Scarb.lock | 115 ++++ cairo/Scarb.toml | 9 +- cairo/src/MultiSigL2.cairo | 524 +++++++++++++----- cairo/src/components/AccessRegistry.cairo | 216 ++++++-- cairo/src/components/BlackListed.cairo | 2 +- cairo/src/components/SuperAdmin2Step.cairo | 10 +- .../components/utils/FallbackAdmin2Step.cairo | 188 ------- cairo/src/contracts/HSTK.cairo | 0 cairo/src/contracts/MultisigL2.cairo | 393 +++++++++++++ cairo/src/interfaces/IaccessRegistry.cairo | 6 + .../src/interfaces/IfallbackAdmin2Step.cairo | 13 - cairo/src/lib.cairo | 33 +- 13 files changed, 1108 insertions(+), 402 deletions(-) delete mode 100644 cairo/src/components/utils/FallbackAdmin2Step.cairo create mode 100644 cairo/src/contracts/HSTK.cairo create mode 100644 cairo/src/contracts/MultisigL2.cairo delete mode 100644 cairo/src/interfaces/IfallbackAdmin2Step.cairo diff --git a/cairo/.tool-versions b/cairo/.tool-versions index 4a51faa..45322ff 100644 --- a/cairo/.tool-versions +++ b/cairo/.tool-versions @@ -1 +1,2 @@ starknet-foundry 0.27.0 +scarb 2.8.4 diff --git a/cairo/Scarb.lock b/cairo/Scarb.lock index eb7dee8..3420067 100644 --- a/cairo/Scarb.lock +++ b/cairo/Scarb.lock @@ -4,3 +4,118 @@ version = 1 [[package]] name = "cairo" version = "0.1.0" +dependencies = [ + "openzeppelin", + "snforge_std", +] + +[[package]] +name = "openzeppelin" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" +dependencies = [ + "openzeppelin_access", + "openzeppelin_account", + "openzeppelin_finance", + "openzeppelin_governance", + "openzeppelin_introspection", + "openzeppelin_merkle_tree", + "openzeppelin_presets", + "openzeppelin_security", + "openzeppelin_token", + "openzeppelin_upgrades", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_access" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" +dependencies = [ + "openzeppelin_introspection", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_account" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" +dependencies = [ + "openzeppelin_introspection", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_finance" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" +dependencies = [ + "openzeppelin_access", + "openzeppelin_token", +] + +[[package]] +name = "openzeppelin_governance" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" +dependencies = [ + "openzeppelin_access", + "openzeppelin_account", + "openzeppelin_introspection", + "openzeppelin_token", +] + +[[package]] +name = "openzeppelin_introspection" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" + +[[package]] +name = "openzeppelin_merkle_tree" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" + +[[package]] +name = "openzeppelin_presets" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" +dependencies = [ + "openzeppelin_access", + "openzeppelin_account", + "openzeppelin_finance", + "openzeppelin_introspection", + "openzeppelin_token", + "openzeppelin_upgrades", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_security" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" + +[[package]] +name = "openzeppelin_token" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" +dependencies = [ + "openzeppelin_access", + "openzeppelin_account", + "openzeppelin_introspection", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_upgrades" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" + +[[package]] +name = "openzeppelin_utils" +version = "0.19.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" + +[[package]] +name = "snforge_std" +version = "0.27.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.27.0#2d99b7c00678ef0363881ee0273550c44a9263de" diff --git a/cairo/Scarb.toml b/cairo/Scarb.toml index 4c20759..b1ae1eb 100644 --- a/cairo/Scarb.toml +++ b/cairo/Scarb.toml @@ -7,14 +7,13 @@ edition = "2023_11" # ... -[workspace.dependencies] +[dependencies] snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.27.0" } openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.19.0" } +starknet = "2.8.4" [[target.starknet-contract]] - -[dependencies] -starknet = ">=2.5.4" - +casm = true +sierra = true diff --git a/cairo/src/MultiSigL2.cairo b/cairo/src/MultiSigL2.cairo index 7311c71..8cda74c 100644 --- a/cairo/src/MultiSigL2.cairo +++ b/cairo/src/MultiSigL2.cairo @@ -1,152 +1,394 @@ -#[starknet::contract] -pub mod MultiSigL2{ - use starknet::{ContractAddress,get_caller_address}; - use cairo::components::AccessRegistry::AccessRegistryComp; - use cairo::component::SuperAdmin2Step::SuperAdminTwoStep; - use openzeppelin::upgrades::interface::IUpgradeable; - use openzeppelin::upgrades::upgradeable::UpgradeableComponent; +// use starknet::{ContractAddress,ClassHash}; +// #[derive(Copy, Drop, Serde, starknet::Store)] +// pub enum TransactionState { +// Pending, +// Active, +// Queued, +// Expired, +// Executed, +// } - component!(path:AccessRegistryComp , storage:access_registry , event:AccessRegistryEvents); - component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); +// #[starknet::interface] +// pub trait IMultiSigL2 { +// fn upgrade(ref self: TContractState, new_class_hash: ClassHash); +// fn create_blacklist_tx(ref self:TContractState, account:ContractAddress)->felt252; +// fn create_removeBlacklisted_tx(ref self:TContractState, account:ContractAddress)->felt252; +// fn create_recover_token_tx(ref self: TContractState,asset:ContractAddress, receipient:ContractAddress)->felt252; +// fn update_pauseState_tx(ref self:TContractState,state:u8)->felt252; +// fn update_transaction_state(ref self:TContractState,tx_id:felt252)->TransactionState; +// fn approve_transaction(ref self: TContractState,tx_id:felt252); +// fn revoke_signatory(ref self: TContractState,tx_id:felt252); +// fn execute_transaction(ref self: TContractState,tx_id:felt252); +// fn is_valid_tx(self:@TContractState,tx_id:felt252)->bool; +// } - impl UpgradeableInternalImpl = UpgradeableComponent::InternalImp; - impl AccessControlInternalImpl = AccessRegistryComp::InternalImpl; +// #[starknet::contract] +// pub mod MultiSigL2{ - #[abi(embed_v0)] - impl AccessControlImpl = - AccessRegistryComp::AccessControlImpl; +// use starknet::{ContractAddress,ClassHash,SyscallResultTrait}; +// use starknet::{get_caller_address,get_block_timestamp}; +// use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; +// use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; +// use core::array::ArrayTrait; +// use core::option::OptionTrait; +// use cairo::components::AccessRegistry::AccessRegistryComp; +// use cairo::components::SuperAdmin2Step::SuperAdminTwoStep; +// use openzeppelin::upgrades::{UpgradeableComponent, interface::IUpgradeable}; +// use openzeppelin::introspection::src5::SRC5Component; +// use super::TransactionState; +// use core::num::traits::Zero; +// use starknet::StorageBaseAddress; +// use core::pedersen::PedersenTrait; +// use starknet::account::Call; +// use starknet::syscalls::call_contract_syscall; - #[abi(embed_v0)] - impl SuperAdminTwoStepImpl = - SuperAdminTwoStep::SuperAdminTwoStepImpl; +// component!(path: SuperAdminTwoStep , storage: super_admin_two_step , event: SuperAdminTwoStepEvents); +// component!(path: AccessRegistryComp , storage: access_registry , event: AccessRegistryEvents); +// component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); +// component!(path: SRC5Component, storage: src5, event: SRC5Event); +// // impl UpgradeableInternalImpl = UpgradeableComponent::In; +// // impl AccessControlInternalImpl = AccessRegistryComp::AccessRegistyImpl; - // Constants - const SIGNER_WINDOW: u64 = 86400; // 24 hours in seconds - const APPROVAL_THRESHOLD: u64 = 60; // 60% of signers must approve +// // Constants +// pub const SIGNER_WINDOW: u64 = 86400; // 24 hours in seconds +// pub const APPROVAL_THRESHOLD: u64 = 60; // 60% of signers must approve - // Function selectors as constants - const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); - const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); - const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); - const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress)"); - - #[derive(Copy, Drop, Serde, starknet::Store)] - enum TransactionState { - Pending, - Active, - Queued, - Expired, - Executed, - } - - #[derive(Drop, Serde, starknet::Store)] - struct Transaction { - proposer: ContractAddress, - selector: felt252, - params : felt252, - proposed_at: u64, - first_sign_at: u64, - approvals: u64, - state: TransactionState - } - - #[storage] - struct Storage { - - token_contract: ContractAddress, - transactions: LegacyMap, - has_approved: LegacyMap<(u256, ContractAddress), bool>, - transaction_exists: LegacyMap, - signer_functions: LegacyMap, - #[substorage(v0)] - access_registry:AccessRegistryComp::Storage, - #[substorage(v0)] - upgradeable: UpgradeableComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - TransactionProposed: TransactionProposed, - TransactionApproved: TransactionApproved, - SignatoryRevoked: SignatoryRevoked, - TransactionExecuted: TransactionExecuted, - TransactionExpired: TransactionExpired, - TransactionStateChanged: TransactionStateChanged, - #[flat] - AccessRegistryEvents:AccessRegistryComp::Events, - #[flat] - UpgradeableEvent: UpgradeableComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event, - } - } - - #[derive(Drop, starknet::Event)] - struct TransactionProposed { - tx_id: felt252, - proposer:ContractAddress, - proposed_at: u64, - } - - #[derive(Drop, starknet::Event)] - struct TransactionApproved { - tx_id: felt252, - signer: ContractAddress, - } - - #[derive(Drop, starknet::Event)] - struct SignatoryRevoked { - tx_id: felt252, - revoker: ContractAddress, - } - - #[derive(Drop, starknet::Event)] - struct TransactionExecuted { - tx_id: felt252 - } - - #[derive(Drop, starknet::Event)] - struct TransactionExpired { - tx_id: felt252 - } - - #[derive(Drop, starknet::Event)] - struct TransactionStateChanged { - tx_id: felt252, - new_state: TransactionState, - } - - pub mod Error{ - pub const ZERO_ADDRESS:felt252 = 'CAlldata consist Zero Address'; - } - - #[constructor] - fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress){ - assert(!token_l2.is_zero() && !super_admin.is_zero(),Error::ZERO_ADDRESS); - self.access_registry.initializer(super_admin); - self.token_contract.write(token_l2); - } - - - // Upgradable - #[abi(embed_v0)] - impl UpgradeableImpl of IUpgradeable { - fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { - self.accessControl.assert_only_super_admin(); - self.upgradeable._upgrade(new_class_hash); - } - } - - // impl MultiSigL2Impl< - // TContractState, - // +Has \ No newline at end of file +// // Function selectors as constants +// pub const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); +// pub const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); +// pub const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); +// pub const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); + +// #[derive(Drop, Serde, starknet::Store)] +// pub struct Transaction { +// proposer: ContractAddress, +// selector: felt252, +// params : Span, +// proposed_at: u64, +// first_sign_at: u64, +// approvals: u64, +// state: TransactionState +// } + +// #[storage] +// pub struct Storage { +// #[substorage(v0)] +// super_admin_two_step:SuperAdminTwoStep::Storage, +// #[substorage(v0)] +// access_registry:AccessRegistryComp::Storage, +// #[substorage(v0)] +// upgradeable: UpgradeableComponent::Storage, +// #[substorage(v0)] +// src5: SRC5Component::Storage, +// token_contract: ContractAddress, +// transactions: LegacyMap, +// has_approved: LegacyMap<(felt252, ContractAddress), bool>, +// transaction_exists: LegacyMap, +// signer_functions: LegacyMap + + +// } + +// #[event] +// #[derive(Drop,starknet::Event)] +// pub enum Event{ +// TransactionProposed: TransactionProposed, +// TransactionApproved: TransactionApproved, +// SignatoryRevoked: SignatoryRevoked, +// TransactionExecuted: TransactionExecuted, +// TransactionExpired: TransactionExpired, +// TransactionStateChanged: TransactionStateChanged, +// #[flat] +// SuperAdminTwoStepEvents: SuperAdminTwoStep::Event, +// #[flat] +// AccessRegistryEvents: AccessRegistryComp::Event, +// #[flat] +// UpgradeableEvent: UpgradeableComponent::Event, +// #[flat] +// SRC5Event: SRC5Component::Event +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionProposed { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub proposer:ContractAddress, +// #[key] +// pub proposed_at: u64, +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionApproved { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub signer: ContractAddress, +// } + +// #[derive(Drop,starknet::Event)] +// pub struct SignatoryRevoked { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub revoker: ContractAddress, +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionExecuted { +// #[key] +// pub tx_id: felt252 +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionExpired { +// #[key] +// pub tx_id: felt252 +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionStateChanged { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub new_state: TransactionState, +// } + +// pub mod Error{ +// pub const ZERO_ADDRESS:felt252 = 'CAlldata consist Zero Address'; +// } + +// #[abi(embed_v0)] +// impl AccessControlImpl = +// AccessRegistryComp::AccessControlImpl; + +// #[abi(embed_v0)] +// impl SuperAdminTwoStepImpl = +// SuperAdminTwoStep::SuperAdminTwoStepImpl; + +// #[constructor] +// fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress){ +// assert(!token_l2.is_zero() && !super_admin.is_zero(),Error::ZERO_ADDRESS); +// self.access_registry.initializer(super_admin); +// self.token_contract.write(token_l2); +// } + +// impl MultiSigL2Impl of super::IMultiSigL2{ + +// fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { +// self.access_registry.assert_only_super_admin(); +// self.upgradeable._upgrade(new_class_hash); +// } + +// fn create_blacklist_tx(ref self:ContractState, account:ContractAddress)->felt252 { + +// assert(!account.is_zero(),Error::ZERO_ADDRESS); +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let calldata:Span = array![account.into()]; +// self._route_standarad_transaction(BLACKLIST_ACCOUNT_SELECTOR,calldata) +// } +// fn create_removeBlacklisted_tx(ref self:ContractState, account:ContractAddress)->felt252{ + +// assert(!account.is_zero(),Error::ZERO_ADDRESS); +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let calldata:Span = array![account.into()]; +// self._route_standarad_transaction(REMOVE_BLACKLIST_ACCOUNT_SELECTOR,calldata) + +// } +// fn create_recover_token_tx(ref self: ContractState,asset:ContractAddress, receipient:ContractAddress)->felt252{ + +// assert(!asset.is_zero() &&!receipient.is_zero() ,Error::ZERO_ADDRESS); +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let calldata:Span = array![asset.into(),receipient.into()]; +// self._route_standarad_transaction(RECOVER_TOKENS_SELECTOR,calldata) + +// } +// fn update_pauseState_tx(ref self:ContractState,state:u8)->felt252{ + +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let calldata:Span = array![state.into()]; +// self._route_standarad_transaction(PAUSE_STATE_SELECTOR,calldata) + +// } +// fn update_transaction_state(ref self:ContractState,tx_id:felt252)->TransactionState{ +// self._assert_transaction_exists(tx_id); +// let mut transaction:Transaction = self.transactions.read(tx_id); + +// if(transaction.state == TransactionState.Expired || transaction.state == TransactionState.Executed){ +// transaction.state +// } +// let current_time = get_block_timestamp(); + +// let isExpired:bool = current_time > transaction.first_sign_at + SIGNER_WINDOW; + +// let new_state:TransactionState = transaction.state; +// let total_signers:u64 = self.access_registry.total_signers(); + +// if(isExpired){ +// if((transaction.approvals * 100) / totalSigner >= APPROVAL_THRESHOLD){ +// new_state = TransactionState.Queued; +// }else{ +// //emit an Insufficient Approval Event +// self.emit( +// TransactionExpired{ +// tx_id: tx_id +// } +// ); +// new_state = TransactionState.Expired; +// } +// }else if(transaction.first_sign_at!=0){ +// new_state = TransactionState.Active; +// } + +// if (new_state != transaction.state) { +// transaction.state = newState; +// // self.(emit{TransactionStateChanged(txId, transaction.state)}); +// } + +// newState + +// } +// fn is_valid_tx(self:@ContractState,tx_id:u256)->bool{ +// true +// } + +// fn approve_transaction(ref self: ContractState, tx_id: felt252) { + +// self._assert_transaction_exists(tx_id); +// let caller = get_caller_address(); +// let current_timestamp =get_block_timestamp(); +// assert(self.access_registry.is_signer(caller), 'Not a signer'); +// assert(!self.has_approved.read((tx_id, caller)), 'Already approved'); + +// let mut transaction = self.transactions.read(tx_id); +// let current_state = self.update_transaction_state(tx_id); + +// assert( +// current_state == TransactionState::Pending || +// current_state == TransactionState::Active, +// 'Invalid state' +// ); + +// if transaction.approvals == 0 { +// transaction.first_sign_at = current_timestamp; +// } + +// transaction.approvals += 1; +// self.has_approved.write((tx_id, caller), true); +// self.transactions.write(tx_id, transaction); + +// self.emit(TransactionApproved { tx_id, signer: caller }); +// } +// fn revoke_signatory(ref self: ContractState,tx_id:felt252){ + +// self._assert_transaction_exists(tx_id); +// let caller = get_caller_address(); +// let current_timestamp =get_block_timestamp(); +// assert(self.access_registry.is_signer(caller), 'Not a signer'); +// assert(self.has_approved.read((tx_id, caller)), 'Not approved'); + +// let mut transaction = self.transactions.read(tx_id); +// let current_state:TransactionState = self.update_transaction_state(tx_id); + +// assert( +// current_state == TransactionState::Active, +// 'Invalid state for Revoke Signature' +// ); +// transaction.approvals -= 1; +// self.has_approved.write((tx_id, caller), false); +// self.transactions.write(tx_id, transaction); +// self.emit(SignatoryRevoked { tx_id, signer: caller }); + + +// } +// fn execute_transaction(ref self: ContractState, tx_id: felt252) { +// self._assert_transaction_exists(tx_id); +// let mut transaction = self.transactions.read(tx_id); +// let current_state = self.update_transaction_state(tx_id); + +// assert(current_state == TransactionState::Queued, 'Invalid state'); +// transaction.state = TransactionState::Executed; +// self.transactions.write(tx_id, transaction); + +// self._call(transaction.selector, transaction.params); +// self.emit(TransactionExecuted { tx_id }); +// } + +// } +// #[generate_trait] +// impl InternalImpl of InternalTrait { +// fn _route_standarad_transaction(ref self: ContractState, function_selector: felt252 , calldata:Array)->felt252{ +// let caller: ContractAddress = get_caller_address(); +// let super_admin:ContractAddress = self.super_admin_two_step.super_admin(); +// if(caller==super_admin){ +// self._call(function_selector,calldata) +// }else{ +// self._create_transaction(function_selector,calldata) +// } + +// } + +// fn _assert_transaction_exists(ref self: ContractState, tx_id: felt252) { +// assert(self.transaction_exists.read(tx_id), 'Transaction not found'); +// } + +// fn _create_transaction( +// ref self: ContractState, +// selector: felt252, +// params: Span +// ) -> felt252 { +// let caller = get_caller_address(); +// let is_signer = self.access_registry.is_signer(caller); +// let timestamp = get_block_timestamp(); +// let is_valid_function:bool = self.signer_functions.read(selector); + +// assert(is_valid_function && is_signer , 'Unauthorized'); + +// let tx_id = PedersenTrait::new(0).update_with(params).update_with(timestamp).update_with(selector).finalize(); + + +// //For multiple transaction with same params andd calldata in a single Block. +// assert(!self.transaction_exists.read(tx_id), 'Transaction exists'); + +// self.transaction_exists.write(tx_id, true); +// let transaction:Transaction = Transaction { +// proposer: caller, +// selector, +// params, +// proposed_at: timestamp, +// first_sign_at: 0, +// approvals: 0, +// state: TransactionState::Pending +// }; + +// self.transactions.write(tx_id, transaction); +// self.emit(TransactionProposed { +// tx_id, +// proposer: caller, +// proposed_at: get_block_timestamp() +// }); + +// tx_id +// } + +// fn _call(self:@ContractState, function_selector:felt252, calldata:Array)->felt252{ +// get_block_timestamp().into() + +// } + + +// // const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); +// // const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); +// // const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); +// // const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); + + +// } + +// } + diff --git a/cairo/src/components/AccessRegistry.cairo b/cairo/src/components/AccessRegistry.cairo index 304189a..c3b6fd5 100644 --- a/cairo/src/components/AccessRegistry.cairo +++ b/cairo/src/components/AccessRegistry.cairo @@ -1,28 +1,34 @@ //dsdedewded #[starknet::component] -mod AccessRegistryComp { - use starknet::get_caller_address; +pub mod AccessRegistryComp { + use starknet::{get_caller_address,get_block_timestamp}; use starknet::ContractAddress; use cairo::interfaces::IaccessRegistry::IAccessRegistryComponent; - use cairo::components::SuperAdmin2Step::SuperAdminTwoStep::SuperAdminTwoStepImpl; - use cairo::components::SuperAdmin2Step::SuperAdminTwoStep::InternalImpl; - use cairo::components::SuperAdmin2Step::SuperAdminTwoStep; + // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp::SuperAdminTwoStepImpl; + // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp::InternalImpl; + // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp; use core::num::traits::Zero; + // use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; + // use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; #[storage] - struct Storage { - total_signers: u256, - signers: LegacyMap:: + pub struct Storage { + super_admin:ContractAddress, + pending_admin: ContractAddress, + handover_expires: u64, + total_signers: u64, + signers:LegacyMap::, } - #[event] #[derive(Drop, PartialEq, starknet::Event)] pub enum Event { SignerAdded: SignerAdded, SignerRemoved: SignerRemoved, - SignerRenounced: SignerRenounced + SignerRenounced: SignerRenounced, + SuperOwnershipTransferred: SuperOwnershipTransferred, + SuperOwnershipTransferStarted: SuperOwnershipTransferStarted } #[derive(Drop, PartialEq, starknet::Event)] @@ -44,6 +50,21 @@ mod AccessRegistryComp { #[key] pub to: ContractAddress } + #[derive(Drop, PartialEq, starknet::Event)] + pub struct SuperOwnershipTransferred { + #[key] + pub previous_super_admin: ContractAddress, + #[key] + pub new_super_admin: ContractAddress, + } + + #[derive(Drop, PartialEq, starknet::Event)] + pub struct SuperOwnershipTransferStarted { + #[key] + pub previous_super_admin: ContractAddress, + #[key] + pub new_super_admin: ContractAddress, + } pub mod Error { pub const ZERO_ADDRESS: felt252 = 'Zero Address'; @@ -51,26 +72,34 @@ mod AccessRegistryComp { pub const Already_Signer: felt252 = 'Already a Signer'; pub const SuperAdminCannotRemoved: felt252 = 'Super Admin Cannot Removed'; pub const NonExistingSigner: felt252 = 'Non Existing Signer'; + pub const NOT_OWNER: felt252 = 'Caller is not super admin'; + pub const NOT_PENDING_OWNER: felt252 = 'Caller not pending super admin'; + pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; + pub const ZERO_ADDRESS_OWNER: felt252 = 'Calldata consist zero address'; + pub const HANDOVER_EXPIRED: felt252 = 'Super Admin Ownership expired'; } - #[embeddable_as(AccessRegistry)] - impl AccessRegistyImpl< + #[embeddable_as(AccessRegistryImpl)] + pub impl AccessRegisty< TContractState, +HasComponent, - impl SuperAdminTwoStepImpl: SuperAdminTwoStep::HasComponent, + // impl SuperAdminTwoStepImpl: SuperAdminTwoStepComp::HasComponent, +Drop > of IAccessRegistryComponent> { fn is_signer(self: @ComponentState, account: ContractAddress) -> bool { self.signers.read(account) } + fn total_signer(self:@ComponentState)->u64{ + self.total_signers.read() + } fn add_signer(ref self: ComponentState, new_signer: ContractAddress) { assert(!new_signer.is_zero(), Error::ZERO_ADDRESS); assert(!self.is_signer(new_signer), Error::Already_Signer); - let super_admin_comp = get_dep_component!(@self, SuperAdminTwoStepImpl); - super_admin_comp.assert_only_super_admin(); + // let super_admin_comp = get_dep_component!(@self, SuperAdminTwoStepImpl); + self.assert_only_super_admin(); self.signers.write(new_signer, true); self.total_signers.write(self.total_signers.read() + 1); self.emit(SignerAdded { signer: new_signer }); @@ -82,11 +111,9 @@ mod AccessRegistryComp { assert(!existing_owner.is_zero(), Error::ZERO_ADDRESS); assert(self.is_signer(existing_owner), Error::NonExistingSigner); - let super_admin_comp = get_dep_component!(@self, SuperAdminTwoStepImpl); - - let super_admin: ContractAddress = super_admin_comp.super_admin(); + let super_admin: ContractAddress = self.super_admin.read(); assert(existing_owner != super_admin, Error::SuperAdminCannotRemoved); - super_admin_comp.assert_only_super_admin(); + self.assert_only_super_admin(); self.signers.write(existing_owner, false); self.total_signers.write(self.total_signers.read() - 1); @@ -102,36 +129,78 @@ mod AccessRegistryComp { !self.is_signer(signer), Error::Already_Signer ); //new signer cannot be existing signer - let super_admin_comp = get_dep_component!(@self, SuperAdminTwoStepImpl); - let super_admin: ContractAddress = super_admin_comp.super_admin(); + let super_admin: ContractAddress = self.super_admin.read(); assert(caller != super_admin, Error::SuperAdminCannotRemoved); //signer cannot be remove // check it needs to be existing owner self._renounce_signership(caller, signer); } - fn accept_super_adminship(ref self: ComponentState) { + fn accept_super_adminship(ref self: ComponentState){ let caller: ContractAddress = get_caller_address(); - let mut super_admin_comp = get_dep_component_mut!(ref self, SuperAdminTwoStepImpl); - let super_admin: ContractAddress = super_admin_comp.super_admin(); - super_admin_comp._accept_super_adminship(); - self._renounce_signership(caller, super_admin); + let super_admin:ContractAddress = self.super_admin.read(); + self._accept_super_adminship(); + self._renounce_signership(caller,super_admin); + } + + // fn initializer(ref self: ComponentState, super_admin: ContractAddress) { + + // .initializer(super_admin); + // self.total_signers.write(1); + // self.signers.write(super_admin, true); + // } + + // fn initializer( + // ref self: ComponentState, + // parent_storage: &mut Storage + // ) { + // let mut super_admin_comp = get_dep_component_mut!(ref self, SuperAdminTwoStepImpl); + // super_admin_comp.initializer(parent_storage.super_admin); + // self.total_signers.write(1); + // self.signers.write(parent_storage.super_admin, true); + // } + + fn super_admin(self: @ComponentState) -> ContractAddress { + self.super_admin.read() + } + + /// Returns the address of the pending super_admin. + fn pending_super_admin(self: @ComponentState) -> ContractAddress { + self.pending_admin.read() + } + + //Returns the handover expiry of the pending super_admin + fn super_handover_expires_at(self: @ComponentState) -> u64 { + self.handover_expires.read() + } + + + /// Starts the two-step super_adminship transfer process by setting the pending super_admin. + /// + /// Requirements: + /// + /// - The caller is the contract super_admin. + /// + /// Emits an `OwnershipTransferStarted` event. + fn transfer_super_adminship( + ref self: ComponentState, new_super_admin: ContractAddress + ) { + self.assert_only_super_admin(); + self._propose_super_admin(new_super_admin); + } + + /// Returns the time for which handover is valid for pending super_admin. + fn super_admin_ownership_valid_for(self: @ComponentState) -> u64 { + 72 * 3600 } + } #[generate_trait] - impl InternalImp< + pub impl InternalImp< TContractState, +HasComponent, - impl SuperAdminTwoStepImpl: SuperAdminTwoStep::HasComponent, +Drop > of InternalTrait { - fn initializer(ref self: ComponentState, super_admin: ContractAddress) { - let mut super_admin_comp = get_dep_component_mut!(ref self, SuperAdminTwoStepImpl); - super_admin_comp.initializer(super_admin); - self.total_signers.write(1); - self.signers.write(super_admin, true); - } - fn _renounce_signership( ref self: ComponentState, _from: ContractAddress, _to: ContractAddress ) { @@ -140,5 +209,82 @@ mod AccessRegistryComp { self.emit(SignerRenounced { from: _from, to: _to }); } + /// Sets the contract's initial super_admin. + /// + /// This function should be called at construction time. + fn initializer(ref self: ComponentState, super_admin: ContractAddress) { + self._transfer_super_adminship(super_admin); + self.total_signers.write(1); + self.signers.write(super_admin, true); + } + + /// Panics if called by any account other than the super_admin. Use this + /// to restrict access to certain functions to the super_admin. + fn assert_only_super_admin(self: @ComponentState) { + let super_admin = self.super_admin.read(); + let caller = get_caller_address(); + assert(!caller.is_zero(), Error::ZERO_ADDRESS_CALLER); + assert(caller == super_admin, Error::NOT_OWNER); + } + + /// Finishes the two-step super_adminship transfer process by accepting the super_adminship. + /// Can only be called by the pending super_admin. + /// + /// Requirements: + /// + /// - The caller is the pending super_admin. + /// + /// Emits an `OwnershipTransferred` event. + fn _accept_super_adminship(ref self: ComponentState) { + let caller = get_caller_address(); + let pending_super_admin = self.pending_admin.read(); + let super_adminship_expires_at: u64 = self.handover_expires.read(); + assert(caller == pending_super_admin, Error::NOT_PENDING_OWNER); + assert(get_block_timestamp() <= super_adminship_expires_at, Error::HANDOVER_EXPIRED); + self._transfer_super_adminship(pending_super_admin); + } + + /// Transfers super_adminship of the contract to a new address and resets + /// the pending super_admin to the zero address. + /// + /// Internal function without access restriction. + /// + /// Emits an `OwnershipTransferred` event. + fn _transfer_super_adminship( + ref self: ComponentState, new_super_admin: ContractAddress + ) { + self.pending_admin.write(Zero::zero()); + self.handover_expires.write(0); + + let previous_super_admin: ContractAddress = self.super_admin.read(); + self.super_admin.write(new_super_admin); + self + .emit( + SuperOwnershipTransferred { + previous_super_admin: previous_super_admin, new_super_admin: new_super_admin + } + ); + } + + /// Sets a new pending super_admin. + /// + /// Internal function without access restriction. + /// + /// Emits an `OwnershipTransferStarted` event. + fn _propose_super_admin( + ref self: ComponentState, new_super_admin: ContractAddress + ) { + let previous_super_admin = self.super_admin.read(); + self.pending_admin.write(new_super_admin); + let super_adminship_expires_at = get_block_timestamp() + + 72 * 3600; + self.handover_expires.write(super_adminship_expires_at); + self + .emit( + SuperOwnershipTransferStarted { + previous_super_admin: previous_super_admin, new_super_admin: new_super_admin + } + ); + } } } diff --git a/cairo/src/components/BlackListed.cairo b/cairo/src/components/BlackListed.cairo index 997a9a3..f3cc3dc 100644 --- a/cairo/src/components/BlackListed.cairo +++ b/cairo/src/components/BlackListed.cairo @@ -11,7 +11,7 @@ mod BlackListedComp { #[storage] struct Storage { - blacklisted_account: LegacyMap, + blacklisted_account: LegacyMap::, multi_sig: ContractAddress, } diff --git a/cairo/src/components/SuperAdmin2Step.cairo b/cairo/src/components/SuperAdmin2Step.cairo index ad20934..369353d 100644 --- a/cairo/src/components/SuperAdmin2Step.cairo +++ b/cairo/src/components/SuperAdmin2Step.cairo @@ -14,7 +14,7 @@ /// transfer where the new super_admin first has to accept their super_adminship to /// finalize the transfer. #[starknet::component] -pub mod SuperAdminTwoStep { +pub mod SuperAdminTwoStepComp { use core::num::traits::Zero; use cairo::interfaces::IsuperAdmin2Step::ISuperAdminTwoStep; // use cairo_starknet::interfaces::IsuperAdmin2Step; @@ -62,9 +62,9 @@ pub mod SuperAdminTwoStep { } /// Adds support for two step super_adminship transfer. - #[embeddable_as(SuperAdminTwoStep)] - pub impl SuperAdminTwoStepImpl< - TContractState, +HasComponent + #[embeddable_as(SuperAdminTwoStepImpl)] + pub impl SuperAdminTwoStep< + TContractState, +HasComponent, +Drop > of IsuperAdmin2Step::ISuperAdminTwoStep> { /// Returns the address of the current super_admin. fn super_admin(self: @ComponentState) -> ContractAddress { @@ -172,7 +172,7 @@ pub mod SuperAdminTwoStep { let previous_super_admin = self.super_admin.read(); self.pending_admin.write(new_super_admin); let super_adminship_expires_at = get_block_timestamp() - + self.super_admin_ownership_valid_for(); + + 72 * 3600; self.handover_expires.write(super_adminship_expires_at); self .emit( diff --git a/cairo/src/components/utils/FallbackAdmin2Step.cairo b/cairo/src/components/utils/FallbackAdmin2Step.cairo deleted file mode 100644 index ac3a7a8..0000000 --- a/cairo/src/components/utils/FallbackAdmin2Step.cairo +++ /dev/null @@ -1,188 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.19.0 (access/ownable/ownable.cairo) - -/// # Ownable Component -/// -/// The Ownable component provides a basic access control mechanism, where -/// there is an account (an fallback_admin) that can be granted exclusive access to -/// specific functions. -/// -/// The initial fallback_admin can be set by using the `initializer` function in -/// construction time. This can later be changed with `transfer_fallback_adminship`. -/// -/// The component also offers functionality for a two-step fallback_adminship -/// transfer where the new fallback_admin first has to accept their fallback_adminship to -/// finalize the transfer. -#[starknet::component] -pub mod FallbackAdminTwoStep { - use core::num::traits::Zero; - use cairo::interfaces::IfallbackAdmin2Step::IFallbackAdminTwoStep; - // use cairo_starknet::interfaces::IsuperAdmin2Step; - use cairo::interfaces::IfallbackAdmin2Step; - - use starknet::ContractAddress; - use starknet::{get_caller_address, get_block_timestamp}; - - #[storage] - pub struct Storage { - pub fallback_admin: ContractAddress, - pub pending_admin: ContractAddress, - pub handover_expires: u64 - } - - #[event] - #[derive(Drop, PartialEq, starknet::Event)] - pub enum Event { - FallbackOwnershipTransferred: FallbackOwnershipTransferred, - FallbackOwnershipTransferStarted: FallbackOwnershipTransferStarted - } - - #[derive(Drop, PartialEq, starknet::Event)] - pub struct FallbackOwnershipTransferred { - #[key] - pub previous_fallback_admin: ContractAddress, - #[key] - pub new_fallback_admin: ContractAddress, - } - - #[derive(Drop, PartialEq, starknet::Event)] - pub struct FallbackOwnershipTransferStarted { - #[key] - pub previous_fallback_admin: ContractAddress, - #[key] - pub new_fallback_admin: ContractAddress, - } - - pub mod Errors { - pub const NOT_OWNER: felt252 = 'Caller is not FB admin'; - pub const NOT_PENDING_OWNER: felt252 = 'Caller is not pending FB admin'; - pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; - pub const ZERO_ADDRESS_OWNER: felt252 = 'New FB is the zero address'; - pub const HANDOVER_EXPIRED: felt252 = 'Super Admin Ownership expired'; - } - - /// Adds support for two step fallback_adminship transfer. - #[embeddable_as(FallbackAdminTwoStepImpl)] - impl FallbackAdminTwoStep< - TContractState, +HasComponent - > of IfallbackAdmin2Step::IFallbackAdminTwoStep> { - /// Returns the address of the current fallback_admin. - fn fallback_admin(self: @ComponentState) -> ContractAddress { - self.fallback_admin.read() - } - - /// Returns the address of the pending fallback_admin. - fn pending_fallback_admin(self: @ComponentState) -> ContractAddress { - self.pending_admin.read() - } - - //Returns the handover expiry of the pending fallback_admin - fn fallback_handover_expires_at(self: @ComponentState) -> u64 { - self.handover_expires.read() - } - - /// Finishes the two-step fallback_adminship transfer process by accepting the fallback_adminship. - /// Can only be called by the pending fallback_admin. - /// - /// Requirements: - /// - /// - The caller is the pending fallback_admin. - /// - /// Emits an `OwnershipTransferred` event. - fn accept_fallback_adminship(ref self: ComponentState) { - let caller = get_caller_address(); - let pending_fallback_admin = self.pending_admin.read(); - let fallback_adminship_expires_at: u64 = self.handover_expires.read(); - assert(caller == pending_fallback_admin, Errors::NOT_PENDING_OWNER); - assert( - get_block_timestamp() <= fallback_adminship_expires_at, Errors::HANDOVER_EXPIRED - ); - self._transfer_fallback_adminship(pending_fallback_admin); - } - - /// Starts the two-step fallback_adminship transfer process by setting the pending fallback_admin. - /// - /// Requirements: - /// - /// - The caller is the contract fallback_admin. - /// - /// Emits an `OwnershipTransferStarted` event. - fn transfer_fallback_adminship( - ref self: ComponentState, new_fallback_admin: ContractAddress - ) { - self.assert_only_fallback_admin(); - self._propose_fallback_admin(new_fallback_admin); - } - - /// Returns the time for which handover is valid for pending fallback_admin. - fn fallback_admin_ownership_valid_for(self: @ComponentState) -> u64 { - 72 * 3600 - } - } - - #[generate_trait] - pub impl InternalImpl< - TContractState, +HasComponent - > of InternalTrait { - /// Sets the contract's initial fallback_admin. - /// - /// This function should be called at construction time. - fn initializer(ref self: ComponentState, fallback_admin: ContractAddress) { - self._transfer_fallback_adminship(fallback_admin); - } - - /// Panics if called by any account other than the fallback_admin. Use this - /// to restrict access to certain functions to the fallback_admin. - fn assert_only_fallback_admin(self: @ComponentState) { - let fallback_admin = self.fallback_admin.read(); - let caller = get_caller_address(); - assert(!caller.is_zero(), Errors::ZERO_ADDRESS_CALLER); - assert(caller == fallback_admin, Errors::NOT_OWNER); - } - - /// Transfers fallback_adminship of the contract to a new address and resets - /// the pending fallback_admin to the zero address. - /// - /// Internal function without access restriction. - /// - /// Emits an `OwnershipTransferred` event. - fn _transfer_fallback_adminship( - ref self: ComponentState, new_fallback_admin: ContractAddress - ) { - self.pending_admin.write(Zero::zero()); - self.handover_expires.write(0); - - let previous_fallback_admin: ContractAddress = self.fallback_admin.read(); - self.fallback_admin.write(new_fallback_admin); - self - .emit( - FallbackOwnershipTransferred { - previous_fallback_admin: previous_fallback_admin, - new_fallback_admin: new_fallback_admin - } - ); - } - - /// Sets a new pending fallback_admin. - /// - /// Internal function without access restriction. - /// - /// Emits an `OwnershipTransferStarted` event. - fn _propose_fallback_admin( - ref self: ComponentState, new_fallback_admin: ContractAddress - ) { - let previous_fallback_admin = self.fallback_admin.read(); - self.pending_admin.write(new_fallback_admin); - let fallback_adminship_expires_at = get_block_timestamp() - + self.fallback_admin_ownership_valid_for(); - self.handover_expires.write(fallback_adminship_expires_at); - self - .emit( - FallbackOwnershipTransferStarted { - previous_fallback_admin: previous_fallback_admin, - new_fallback_admin: new_fallback_admin - } - ); - } - } -} diff --git a/cairo/src/contracts/HSTK.cairo b/cairo/src/contracts/HSTK.cairo new file mode 100644 index 0000000..e69de29 diff --git a/cairo/src/contracts/MultisigL2.cairo b/cairo/src/contracts/MultisigL2.cairo new file mode 100644 index 0000000..166d3bf --- /dev/null +++ b/cairo/src/contracts/MultisigL2.cairo @@ -0,0 +1,393 @@ + +use starknet::{ContractAddress,ClassHash}; +#[derive(Copy, Drop, Serde, starknet::Store)] +pub enum TransactionState { + Pending, + Active, + Queued, + Expired, + Executed, +} +#[starknet::interface] +pub trait IMultiSigL2 { + fn upgrade(ref self: TContractState, new_class_hash: ClassHash); + fn create_blacklist_tx(ref self:TContractState, account:ContractAddress)->felt252; + fn create_removeBlacklisted_tx(ref self:TContractState, account:ContractAddress)->felt252; + fn create_recover_token_tx(ref self: TContractState,asset:ContractAddress, receipient:ContractAddress)->felt252; + fn update_pauseState_tx(ref self:TContractState,state:u8)->felt252; + fn update_transaction_state(ref self:TContractState,tx_id:felt252)->TransactionState; + fn approve_transaction(ref self: TContractState,tx_id:felt252); + fn revoke_signatory(ref self: TContractState,tx_id:felt252); + fn execute_transaction(ref self: TContractState,tx_id:felt252); + fn is_valid_tx(self:@TContractState,tx_id:felt252)->bool; +} +#[starknet::contract] +mod MultiSigL2{ + + use starknet::{ContractAddress,ClassHash,SyscallResultTrait}; + use starknet::{get_caller_address,get_block_timestamp}; + // use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; + // use starknet::storage::{ + // StoragePointerReadAccess, StoragePointerWriteAccess, StoragePathEntry, Map + // }; + use core::array::ArrayTrait; + use core::option::OptionTrait; + use cairo::components::AccessRegistry::AccessRegistryComp; + // use cairo::components::AccessRegistry::AccessRegistryComp::AccessRegistyImpl; + // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp; + // use cairo::components::SuperAdmin2Step::SuperAdminTwoStep::SuperAdminTwoStepImpl; + use openzeppelin::upgrades::{UpgradeableComponent, interface::IUpgradeable}; + use openzeppelin::introspection::src5::SRC5Component; + use super::TransactionState; + use core::num::traits::Zero; + use core::pedersen::PedersenTrait; + use starknet::account::Call; + use starknet::syscalls::call_contract_syscall; + use core::starknet::event::EventEmitter; + + + component!(path: AccessRegistryComp , storage: accessRegistry , event: AccessRegistryEvents); + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + + /// Upgradeable + impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl; + impl AccessRegistryImpl = AccessRegistryComp::AccessRegisty; + impl AccessRegistryInternalImpl = AccessRegistryComp::InternalImpl; + + // Constants + pub const SIGNER_WINDOW: u64 = 86400; // 24 hours in seconds + pub const APPROVAL_THRESHOLD: u64 = 60; // 60% of signers must approve + + // Function selectors as constants + pub const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); + pub const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); + pub const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); + pub const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); + + #[derive(Drop, Serde, starknet::Store)] + pub struct Transaction { + proposer: ContractAddress, + selector: felt252, + params : Array, + proposed_at: u64, + first_sign_at: u64, + approvals: u64, + state: TransactionState + } + + #[storage] + pub struct Storage { + token_contract: ContractAddress, + transactions: LegacyMap::, + has_approved: LegacyMap::<(felt252, ContractAddress), bool>, + transaction_exists: LegacyMap::, + signer_functions: LegacyMap::, + #[substorage(v0)] + accessRegistry: AccessRegistryComp::Storage, + #[substorage(v0)] + upgradeable: UpgradeableComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop,starknet::Event)] + pub enum Event{ + TransactionProposed: TransactionProposed, + TransactionApproved: TransactionApproved, + SignatoryRevoked: SignatoryRevoked, + TransactionExecuted: TransactionExecuted, + TransactionExpired: TransactionExpired, + TransactionStateChanged: TransactionStateChanged, + #[flat] + AccessRegistryEvents: AccessRegistryComp::Event, + #[flat] + UpgradeableEvent: UpgradeableComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[derive(Drop,starknet::Event)] + pub struct TransactionProposed { + #[key] + pub tx_id: felt252, + #[key] + pub proposer:ContractAddress, + #[key] + pub proposed_at: u64, + } + + #[derive(Drop,starknet::Event)] + pub struct TransactionApproved { + #[key] + pub tx_id: felt252, + #[key] + pub signer: ContractAddress, + } + + #[derive(Drop,starknet::Event)] + pub struct SignatoryRevoked { + #[key] + pub tx_id: felt252, + #[key] + pub revoker: ContractAddress, + } + + #[derive(Drop,starknet::Event)] + pub struct TransactionExecuted { + #[key] + pub tx_id: felt252 + } + + #[derive(Drop,starknet::Event)] + pub struct TransactionExpired { + #[key] + pub tx_id: felt252 + } + + #[derive(Drop,starknet::Event)] + pub struct TransactionStateChanged { + #[key] + pub tx_id: felt252, + #[key] + pub new_state: TransactionState, + } + + pub mod Error{ + pub const ZERO_ADDRESS:felt252 = 'CAlldata consist Zero Address'; + } + + #[abi(embed_v0)] + impl AccessRegistryImpl = + AccessRegistryComp::AccessRegisty; + + #[constructor] + fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress){ + assert(!token_l2.is_zero() && !super_admin.is_zero(),Error::ZERO_ADDRESS); + self.accessRegistry.initializer(super_admin); + self.token_contract.write(token_l2); + } + + #[abi(embed_v0)] + impl MultiSigL2Impl of super::IMultiSigL2{ + + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { + self.accessRegistry.assert_only_super_admin(); + self.upgradeable.upgrade(new_class_hash); + } + + fn create_blacklist_tx(ref self:ContractState, account:ContractAddress)->felt252 { + + assert(!account.is_zero(),Error::ZERO_ADDRESS); + assert(!self.accessRegistry.is_signer(get_caller_address()),'Not Signer'); + let mut calldata:Array = array![]; + Serde::serialize(@account, ref calldata); + self._route_standarad_transaction(BLACKLIST_ACCOUNT_SELECTOR,calldata) + } + fn create_removeBlacklisted_tx(ref self:ContractState, account:ContractAddress)->felt252{ + + assert(!account.is_zero(),Error::ZERO_ADDRESS); + assert(!self.accessRegistry.is_signer(get_caller_address()),'Not Signer'); + let mut calldata:Array = array![]; + Serde::serialize(@account, ref calldata); + self._route_standarad_transaction(REMOVE_BLACKLIST_ACCOUNT_SELECTOR,calldata) + + } + fn create_recover_token_tx(ref self: ContractState,asset:ContractAddress, receipient:ContractAddress)->felt252{ + + assert(!asset.is_zero() &&!receipient.is_zero() ,Error::ZERO_ADDRESS); + assert(!self.accessRegistry.is_signer(get_caller_address()),'Not Signer'); + let mut calldata:Array = array![]; + Serde::serialize(@asset, ref calldata); + Serde::serialize(@receipient, ref calldata); + self._route_standarad_transaction(RECOVER_TOKENS_SELECTOR,calldata) + + } + fn update_pauseState_tx(ref self:ContractState,state:u8)->felt252{ + + assert(!self.accessRegistry.is_signer(get_caller_address()),'Not Signer'); + let mut calldata:Array = array![]; + Serde::serialize(@state, ref calldata); + self._route_standarad_transaction(PAUSE_STATE_SELECTOR,calldata) + + } + fn update_transaction_state(ref self:ContractState,tx_id:felt252)->TransactionState{ + self._assert_transaction_exists(tx_id); + let mut transaction:Transaction = self.transactions.read(tx_id); + + if(transaction.state == TransactionState.Expired || transaction.state == TransactionState.Executed){ + transaction.state + } + let current_time = get_block_timestamp(); + + let isExpired:bool = current_time > transaction.first_sign_at + SIGNER_WINDOW; + + let new_state:TransactionState = transaction.state; + let total_signers:u64 = self.accessRegistry.total_signers(); + + if(isExpired){ + if((transaction.approvals * 100) / total_signers >= APPROVAL_THRESHOLD){ + new_state = TransactionState.Queued; + }else{ + //emit an Insufficient Approval Event + self.emit( + TransactionExpired{ + tx_id: tx_id + } + ); + new_state = TransactionState.Expired; + } + }else if(transaction.first_sign_at!=0){ + new_state = TransactionState.Active; + } + + if (new_state != transaction.state) { + transaction.state = new_state; + // self.(emit{TransactionStateChanged(txId, transaction.state)}); + } + + new_state + + } + fn is_valid_tx(self:@ContractState,tx_id:felt252)->bool{ + true + } + + fn approve_transaction(ref self: ContractState, tx_id: felt252) { + + self._assert_transaction_exists(tx_id); + let caller = get_caller_address(); + let current_timestamp =get_block_timestamp(); + assert(self.accessRegistry.is_signer(caller), 'Not a signer'); + assert(!self.has_approved.read((tx_id, caller)), 'Already approved'); + + let mut transaction = self.transactions.read(tx_id); + let current_state = self.update_transaction_state(tx_id); + + assert( + current_state == TransactionState::Pending || + current_state == TransactionState::Active, + 'Invalid state' + ); + + if transaction.approvals == 0 { + transaction.first_sign_at = current_timestamp; + } + + transaction.approvals += 1; + self.has_approved.write((tx_id, caller), true); + self.transactions.write(tx_id, transaction); + + self.emit(TransactionApproved { tx_id, signer: caller }); + } + fn revoke_signatory(ref self: ContractState,tx_id:felt252){ + + self._assert_transaction_exists(tx_id); + let caller = get_caller_address(); + let current_timestamp =get_block_timestamp(); + assert(self.accessRegistry.is_signer(caller), 'Not a signer'); + assert(self.has_approved.read((tx_id, caller)), 'Not approved'); + + let mut transaction = self.transactions.read(tx_id); + let current_state:TransactionState = self.update_transaction_state(tx_id); + + assert( + current_state == TransactionState::Active, + 'Invalid state for Revoke Signature' + ); + transaction.approvals -= 1; + self.has_approved.write((tx_id, caller), false); + self.transactions.write(tx_id, transaction); + self.emit(SignatoryRevoked { tx_id: tx_id, revoker: caller }); + + + } + fn execute_transaction(ref self: ContractState, tx_id: felt252) { + self._assert_transaction_exists(tx_id); + let mut transaction = self.transactions.read(tx_id); + let current_state = self.update_transaction_state(tx_id); + + assert(current_state == TransactionState::Queued, 'Invalid state'); + transaction.state = TransactionState::Executed; + self.transactions.write(tx_id, transaction); + + self._call(transaction.selector, transaction.params); + self.emit(TransactionExecuted { tx_id }); + } + + } + #[generate_trait] + impl InternalImpl of InternalTrait { + fn _route_standarad_transaction(ref self: ContractState, function_selector: felt252 , calldata:Array)->felt252{ + let caller: ContractAddress = get_caller_address(); + let super_admin:ContractAddress = self.accessRegistry.super_admin(); + if(caller==super_admin){ + self._call(function_selector,calldata) + }else{ + self._create_transaction(function_selector,calldata) + } + + } + + fn _assert_transaction_exists(ref self: ContractState, tx_id: felt252) { + assert(self.transaction_exists.read(tx_id), 'Transaction not found'); + } + + fn _create_transaction( + ref self: ContractState, + selector: felt252, + params: Array + ) -> felt252 { + let caller = get_caller_address(); + let is_signer = self.accessRegistry.is_signer(caller); + let timestamp = get_block_timestamp(); + let is_valid_function:bool = self.signer_functions.read(selector); + + assert(is_valid_function && is_signer , 'Unauthorized'); + + // let tx_id = PedersenTrait::new(0).update_with(params).update_with(timestamp).update_with(selector).finalize(); + let tx_id = get_block_timestamp().into(); + + + //For multiple transaction with same params andd calldata in a single Block. + assert(!self.transaction_exists.read(tx_id), 'Transaction exists'); + + self.transaction_exists.write(tx_id, true); + let transaction:Transaction = Transaction { + proposer: caller, + selector, + params, + proposed_at: timestamp, + first_sign_at: 0, + approvals: 0, + state: TransactionState::Pending + }; + + self.transactions.write(tx_id, transaction); + self.emit(TransactionProposed { + tx_id, + proposer: caller, + proposed_at: get_block_timestamp() + }); + + tx_id + } + + fn _call(self:@ContractState, function_selector:felt252, calldata:Array)->felt252{ + get_block_timestamp().into() + + } + + + // const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); + // const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); + // const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); + // const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); + + + } + +} + diff --git a/cairo/src/interfaces/IaccessRegistry.cairo b/cairo/src/interfaces/IaccessRegistry.cairo index a700fb7..826c610 100644 --- a/cairo/src/interfaces/IaccessRegistry.cairo +++ b/cairo/src/interfaces/IaccessRegistry.cairo @@ -6,4 +6,10 @@ pub trait IAccessRegistryComponent { fn renounce_signership(ref self: TContractState, signer: ContractAddress); fn is_signer(self: @TContractState, account: ContractAddress) -> bool; fn accept_super_adminship(ref self: TContractState); + fn total_signer(self:@TContractState)->u64; + fn super_admin(self: @TContractState) -> ContractAddress; + fn pending_super_admin(self: @TContractState) -> ContractAddress; + fn transfer_super_adminship(ref self: TContractState, new_super_admin: ContractAddress); + fn super_admin_ownership_valid_for(self: @TContractState) -> u64; + fn super_handover_expires_at(self: @TContractState) -> u64; } diff --git a/cairo/src/interfaces/IfallbackAdmin2Step.cairo b/cairo/src/interfaces/IfallbackAdmin2Step.cairo deleted file mode 100644 index 9b2ff64..0000000 --- a/cairo/src/interfaces/IfallbackAdmin2Step.cairo +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -use starknet::ContractAddress; - - -#[starknet::interface] -pub trait IFallbackAdminTwoStep { - fn fallback_admin(self: @TState) -> ContractAddress; - fn pending_fallback_admin(self: @TState) -> ContractAddress; - fn accept_fallback_adminship(ref self: TState); - fn transfer_fallback_adminship(ref self: TState, new_fallback_admin: ContractAddress); - fn fallback_admin_ownership_valid_for(self: @TState) -> u64; - fn fallback_handover_expires_at(self: @TState) -> u64; -} diff --git a/cairo/src/lib.cairo b/cairo/src/lib.cairo index d175855..565878b 100644 --- a/cairo/src/lib.cairo +++ b/cairo/src/lib.cairo @@ -6,22 +6,27 @@ // mod BlackListed; // mod Pausable; // } -pub mod components { - pub mod Pausable; - pub mod BlackListed; - pub mod AccessRegistry; - pub mod SuperAdmin2Step; -} + + pub mod components { + pub mod AccessRegistry; + pub mod Pausable; + pub mod BlackListed; + pub mod SuperAdmin2Step; + + } + + pub mod contracts{ + pub mod MultisigL2; + } + pub mod interfaces { - pub mod Ipausable; - pub mod IblackListed; - pub mod IaccessRegistry; - pub mod IsuperAdmin2Step; - pub mod IfallbackAdmin2Step; + pub mod Ipausable; + pub mod IblackListed; + pub mod IaccessRegistry; + pub mod IsuperAdmin2Step; } -pub mod helpers { + pub mod helpers { pub mod constants; -} + } // pub mod HSTK; -pub mod MultiSigl2; From 086596e4db2eaaa4d9b3158a3428f89dbb2154b6 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Wed, 13 Nov 2024 23:58:53 +0530 Subject: [PATCH 4/8] [BUG_FIX] resolved enum type in multisig[DONE] --- cairo/src/contracts/MultisigL2.cairo | 36 ++++++++++++++++++---------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/cairo/src/contracts/MultisigL2.cairo b/cairo/src/contracts/MultisigL2.cairo index 166d3bf..c831221 100644 --- a/cairo/src/contracts/MultisigL2.cairo +++ b/cairo/src/contracts/MultisigL2.cairo @@ -8,6 +8,18 @@ pub enum TransactionState { Expired, Executed, } + +pub fn resolve_tx_state(state: TransactionState) -> felt252 { + match state { + TransactionState::Pending => 0, + TransactionState::Active => 1, + TransactionState::Queued => 2, + TransactionState::Expired => 3, + TransactionState::Executed => 4, + + } +} + #[starknet::interface] pub trait IMultiSigL2 { fn upgrade(ref self: TContractState, new_class_hash: ClassHash); @@ -38,7 +50,7 @@ mod MultiSigL2{ // use cairo::components::SuperAdmin2Step::SuperAdminTwoStep::SuperAdminTwoStepImpl; use openzeppelin::upgrades::{UpgradeableComponent, interface::IUpgradeable}; use openzeppelin::introspection::src5::SRC5Component; - use super::TransactionState; + use super::{TransactionState,resolve_tx_state}; use core::num::traits::Zero; use core::pedersen::PedersenTrait; use starknet::account::Call; @@ -217,19 +229,19 @@ mod MultiSigL2{ self._assert_transaction_exists(tx_id); let mut transaction:Transaction = self.transactions.read(tx_id); - if(transaction.state == TransactionState.Expired || transaction.state == TransactionState.Executed){ + if resolve_tx_state(transaction.state) == resolve_tx_state(TransactionState::Expired) || resolve_tx_state(transaction.state) == resolve_tx_state(TransactionState::Executed){ transaction.state } let current_time = get_block_timestamp(); let isExpired:bool = current_time > transaction.first_sign_at + SIGNER_WINDOW; - let new_state:TransactionState = transaction.state; + let mut new_state:TransactionState = transaction.state; let total_signers:u64 = self.accessRegistry.total_signers(); if(isExpired){ if((transaction.approvals * 100) / total_signers >= APPROVAL_THRESHOLD){ - new_state = TransactionState.Queued; + new_state = TransactionState::Queued; }else{ //emit an Insufficient Approval Event self.emit( @@ -237,13 +249,13 @@ mod MultiSigL2{ tx_id: tx_id } ); - new_state = TransactionState.Expired; + new_state = TransactionState::Expired; } }else if(transaction.first_sign_at!=0){ - new_state = TransactionState.Active; + new_state = TransactionState::Active; } - if (new_state != transaction.state) { + if (resolve_tx_state(new_state) != resolve_tx_state(transaction.state)) { transaction.state = new_state; // self.(emit{TransactionStateChanged(txId, transaction.state)}); } @@ -267,8 +279,8 @@ mod MultiSigL2{ let current_state = self.update_transaction_state(tx_id); assert( - current_state == TransactionState::Pending || - current_state == TransactionState::Active, + resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Pending) || + resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Active), 'Invalid state' ); @@ -294,7 +306,7 @@ mod MultiSigL2{ let current_state:TransactionState = self.update_transaction_state(tx_id); assert( - current_state == TransactionState::Active, + resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Active), 'Invalid state for Revoke Signature' ); transaction.approvals -= 1; @@ -309,7 +321,7 @@ mod MultiSigL2{ let mut transaction = self.transactions.read(tx_id); let current_state = self.update_transaction_state(tx_id); - assert(current_state == TransactionState::Queued, 'Invalid state'); + assert(resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Queued), 'Invalid state'); transaction.state = TransactionState::Executed; self.transactions.write(tx_id, transaction); @@ -323,7 +335,7 @@ mod MultiSigL2{ fn _route_standarad_transaction(ref self: ContractState, function_selector: felt252 , calldata:Array)->felt252{ let caller: ContractAddress = get_caller_address(); let super_admin:ContractAddress = self.accessRegistry.super_admin(); - if(caller==super_admin){ + if caller==super_admin { self._call(function_selector,calldata) }else{ self._create_transaction(function_selector,calldata) From 9f7e57d0a395f56cbe5727c1fba0a1af180194bd Mon Sep 17 00:00:00 2001 From: Saurabh Date: Thu, 14 Nov 2024 00:01:06 +0530 Subject: [PATCH 5/8] [REFAC]removed unused files[DONE] --- cairo/src/HSTK.cairo | 11 -- cairo/src/MultiSigL2.cairo | 394 ------------------------------------- 2 files changed, 405 deletions(-) delete mode 100644 cairo/src/HSTK.cairo delete mode 100644 cairo/src/MultiSigL2.cairo diff --git a/cairo/src/HSTK.cairo b/cairo/src/HSTK.cairo deleted file mode 100644 index 1358f1e..0000000 --- a/cairo/src/HSTK.cairo +++ /dev/null @@ -1,11 +0,0 @@ -// #[starknet::contract] -// pub mod HSTKContract{ - -// use starknet::{get_caller_address,ContractAddress}; -// use components::BlackListed; -// use components::Pausable; - -// component!(path: BlackListedComponent, storage: black, event: SupplyEvent); - -// } - diff --git a/cairo/src/MultiSigL2.cairo b/cairo/src/MultiSigL2.cairo deleted file mode 100644 index 8cda74c..0000000 --- a/cairo/src/MultiSigL2.cairo +++ /dev/null @@ -1,394 +0,0 @@ - -// use starknet::{ContractAddress,ClassHash}; -// #[derive(Copy, Drop, Serde, starknet::Store)] -// pub enum TransactionState { -// Pending, -// Active, -// Queued, -// Expired, -// Executed, -// } - - -// #[starknet::interface] -// pub trait IMultiSigL2 { -// fn upgrade(ref self: TContractState, new_class_hash: ClassHash); -// fn create_blacklist_tx(ref self:TContractState, account:ContractAddress)->felt252; -// fn create_removeBlacklisted_tx(ref self:TContractState, account:ContractAddress)->felt252; -// fn create_recover_token_tx(ref self: TContractState,asset:ContractAddress, receipient:ContractAddress)->felt252; -// fn update_pauseState_tx(ref self:TContractState,state:u8)->felt252; -// fn update_transaction_state(ref self:TContractState,tx_id:felt252)->TransactionState; -// fn approve_transaction(ref self: TContractState,tx_id:felt252); -// fn revoke_signatory(ref self: TContractState,tx_id:felt252); -// fn execute_transaction(ref self: TContractState,tx_id:felt252); -// fn is_valid_tx(self:@TContractState,tx_id:felt252)->bool; -// } - - -// #[starknet::contract] -// pub mod MultiSigL2{ - -// use starknet::{ContractAddress,ClassHash,SyscallResultTrait}; -// use starknet::{get_caller_address,get_block_timestamp}; -// use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; -// use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; -// use core::array::ArrayTrait; -// use core::option::OptionTrait; -// use cairo::components::AccessRegistry::AccessRegistryComp; -// use cairo::components::SuperAdmin2Step::SuperAdminTwoStep; -// use openzeppelin::upgrades::{UpgradeableComponent, interface::IUpgradeable}; -// use openzeppelin::introspection::src5::SRC5Component; -// use super::TransactionState; -// use core::num::traits::Zero; -// use starknet::StorageBaseAddress; -// use core::pedersen::PedersenTrait; -// use starknet::account::Call; -// use starknet::syscalls::call_contract_syscall; - -// component!(path: SuperAdminTwoStep , storage: super_admin_two_step , event: SuperAdminTwoStepEvents); -// component!(path: AccessRegistryComp , storage: access_registry , event: AccessRegistryEvents); -// component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); -// component!(path: SRC5Component, storage: src5, event: SRC5Event); - - -// // impl UpgradeableInternalImpl = UpgradeableComponent::In; -// // impl AccessControlInternalImpl = AccessRegistryComp::AccessRegistyImpl; - -// // Constants -// pub const SIGNER_WINDOW: u64 = 86400; // 24 hours in seconds -// pub const APPROVAL_THRESHOLD: u64 = 60; // 60% of signers must approve - -// // Function selectors as constants -// pub const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); -// pub const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); -// pub const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); -// pub const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); - -// #[derive(Drop, Serde, starknet::Store)] -// pub struct Transaction { -// proposer: ContractAddress, -// selector: felt252, -// params : Span, -// proposed_at: u64, -// first_sign_at: u64, -// approvals: u64, -// state: TransactionState -// } - -// #[storage] -// pub struct Storage { -// #[substorage(v0)] -// super_admin_two_step:SuperAdminTwoStep::Storage, -// #[substorage(v0)] -// access_registry:AccessRegistryComp::Storage, -// #[substorage(v0)] -// upgradeable: UpgradeableComponent::Storage, -// #[substorage(v0)] -// src5: SRC5Component::Storage, -// token_contract: ContractAddress, -// transactions: LegacyMap, -// has_approved: LegacyMap<(felt252, ContractAddress), bool>, -// transaction_exists: LegacyMap, -// signer_functions: LegacyMap - - -// } - -// #[event] -// #[derive(Drop,starknet::Event)] -// pub enum Event{ -// TransactionProposed: TransactionProposed, -// TransactionApproved: TransactionApproved, -// SignatoryRevoked: SignatoryRevoked, -// TransactionExecuted: TransactionExecuted, -// TransactionExpired: TransactionExpired, -// TransactionStateChanged: TransactionStateChanged, -// #[flat] -// SuperAdminTwoStepEvents: SuperAdminTwoStep::Event, -// #[flat] -// AccessRegistryEvents: AccessRegistryComp::Event, -// #[flat] -// UpgradeableEvent: UpgradeableComponent::Event, -// #[flat] -// SRC5Event: SRC5Component::Event -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionProposed { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub proposer:ContractAddress, -// #[key] -// pub proposed_at: u64, -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionApproved { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub signer: ContractAddress, -// } - -// #[derive(Drop,starknet::Event)] -// pub struct SignatoryRevoked { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub revoker: ContractAddress, -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionExecuted { -// #[key] -// pub tx_id: felt252 -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionExpired { -// #[key] -// pub tx_id: felt252 -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionStateChanged { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub new_state: TransactionState, -// } - -// pub mod Error{ -// pub const ZERO_ADDRESS:felt252 = 'CAlldata consist Zero Address'; -// } - -// #[abi(embed_v0)] -// impl AccessControlImpl = -// AccessRegistryComp::AccessControlImpl; - -// #[abi(embed_v0)] -// impl SuperAdminTwoStepImpl = -// SuperAdminTwoStep::SuperAdminTwoStepImpl; - -// #[constructor] -// fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress){ -// assert(!token_l2.is_zero() && !super_admin.is_zero(),Error::ZERO_ADDRESS); -// self.access_registry.initializer(super_admin); -// self.token_contract.write(token_l2); -// } - -// impl MultiSigL2Impl of super::IMultiSigL2{ - -// fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { -// self.access_registry.assert_only_super_admin(); -// self.upgradeable._upgrade(new_class_hash); -// } - -// fn create_blacklist_tx(ref self:ContractState, account:ContractAddress)->felt252 { - -// assert(!account.is_zero(),Error::ZERO_ADDRESS); -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let calldata:Span = array![account.into()]; -// self._route_standarad_transaction(BLACKLIST_ACCOUNT_SELECTOR,calldata) -// } -// fn create_removeBlacklisted_tx(ref self:ContractState, account:ContractAddress)->felt252{ - -// assert(!account.is_zero(),Error::ZERO_ADDRESS); -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let calldata:Span = array![account.into()]; -// self._route_standarad_transaction(REMOVE_BLACKLIST_ACCOUNT_SELECTOR,calldata) - -// } -// fn create_recover_token_tx(ref self: ContractState,asset:ContractAddress, receipient:ContractAddress)->felt252{ - -// assert(!asset.is_zero() &&!receipient.is_zero() ,Error::ZERO_ADDRESS); -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let calldata:Span = array![asset.into(),receipient.into()]; -// self._route_standarad_transaction(RECOVER_TOKENS_SELECTOR,calldata) - -// } -// fn update_pauseState_tx(ref self:ContractState,state:u8)->felt252{ - -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let calldata:Span = array![state.into()]; -// self._route_standarad_transaction(PAUSE_STATE_SELECTOR,calldata) - -// } -// fn update_transaction_state(ref self:ContractState,tx_id:felt252)->TransactionState{ -// self._assert_transaction_exists(tx_id); -// let mut transaction:Transaction = self.transactions.read(tx_id); - -// if(transaction.state == TransactionState.Expired || transaction.state == TransactionState.Executed){ -// transaction.state -// } -// let current_time = get_block_timestamp(); - -// let isExpired:bool = current_time > transaction.first_sign_at + SIGNER_WINDOW; - -// let new_state:TransactionState = transaction.state; -// let total_signers:u64 = self.access_registry.total_signers(); - -// if(isExpired){ -// if((transaction.approvals * 100) / totalSigner >= APPROVAL_THRESHOLD){ -// new_state = TransactionState.Queued; -// }else{ -// //emit an Insufficient Approval Event -// self.emit( -// TransactionExpired{ -// tx_id: tx_id -// } -// ); -// new_state = TransactionState.Expired; -// } -// }else if(transaction.first_sign_at!=0){ -// new_state = TransactionState.Active; -// } - -// if (new_state != transaction.state) { -// transaction.state = newState; -// // self.(emit{TransactionStateChanged(txId, transaction.state)}); -// } - -// newState - -// } -// fn is_valid_tx(self:@ContractState,tx_id:u256)->bool{ -// true -// } - -// fn approve_transaction(ref self: ContractState, tx_id: felt252) { - -// self._assert_transaction_exists(tx_id); -// let caller = get_caller_address(); -// let current_timestamp =get_block_timestamp(); -// assert(self.access_registry.is_signer(caller), 'Not a signer'); -// assert(!self.has_approved.read((tx_id, caller)), 'Already approved'); - -// let mut transaction = self.transactions.read(tx_id); -// let current_state = self.update_transaction_state(tx_id); - -// assert( -// current_state == TransactionState::Pending || -// current_state == TransactionState::Active, -// 'Invalid state' -// ); - -// if transaction.approvals == 0 { -// transaction.first_sign_at = current_timestamp; -// } - -// transaction.approvals += 1; -// self.has_approved.write((tx_id, caller), true); -// self.transactions.write(tx_id, transaction); - -// self.emit(TransactionApproved { tx_id, signer: caller }); -// } -// fn revoke_signatory(ref self: ContractState,tx_id:felt252){ - -// self._assert_transaction_exists(tx_id); -// let caller = get_caller_address(); -// let current_timestamp =get_block_timestamp(); -// assert(self.access_registry.is_signer(caller), 'Not a signer'); -// assert(self.has_approved.read((tx_id, caller)), 'Not approved'); - -// let mut transaction = self.transactions.read(tx_id); -// let current_state:TransactionState = self.update_transaction_state(tx_id); - -// assert( -// current_state == TransactionState::Active, -// 'Invalid state for Revoke Signature' -// ); -// transaction.approvals -= 1; -// self.has_approved.write((tx_id, caller), false); -// self.transactions.write(tx_id, transaction); -// self.emit(SignatoryRevoked { tx_id, signer: caller }); - - -// } -// fn execute_transaction(ref self: ContractState, tx_id: felt252) { -// self._assert_transaction_exists(tx_id); -// let mut transaction = self.transactions.read(tx_id); -// let current_state = self.update_transaction_state(tx_id); - -// assert(current_state == TransactionState::Queued, 'Invalid state'); -// transaction.state = TransactionState::Executed; -// self.transactions.write(tx_id, transaction); - -// self._call(transaction.selector, transaction.params); -// self.emit(TransactionExecuted { tx_id }); -// } - -// } -// #[generate_trait] -// impl InternalImpl of InternalTrait { -// fn _route_standarad_transaction(ref self: ContractState, function_selector: felt252 , calldata:Array)->felt252{ -// let caller: ContractAddress = get_caller_address(); -// let super_admin:ContractAddress = self.super_admin_two_step.super_admin(); -// if(caller==super_admin){ -// self._call(function_selector,calldata) -// }else{ -// self._create_transaction(function_selector,calldata) -// } - -// } - -// fn _assert_transaction_exists(ref self: ContractState, tx_id: felt252) { -// assert(self.transaction_exists.read(tx_id), 'Transaction not found'); -// } - -// fn _create_transaction( -// ref self: ContractState, -// selector: felt252, -// params: Span -// ) -> felt252 { -// let caller = get_caller_address(); -// let is_signer = self.access_registry.is_signer(caller); -// let timestamp = get_block_timestamp(); -// let is_valid_function:bool = self.signer_functions.read(selector); - -// assert(is_valid_function && is_signer , 'Unauthorized'); - -// let tx_id = PedersenTrait::new(0).update_with(params).update_with(timestamp).update_with(selector).finalize(); - - -// //For multiple transaction with same params andd calldata in a single Block. -// assert(!self.transaction_exists.read(tx_id), 'Transaction exists'); - -// self.transaction_exists.write(tx_id, true); -// let transaction:Transaction = Transaction { -// proposer: caller, -// selector, -// params, -// proposed_at: timestamp, -// first_sign_at: 0, -// approvals: 0, -// state: TransactionState::Pending -// }; - -// self.transactions.write(tx_id, transaction); -// self.emit(TransactionProposed { -// tx_id, -// proposer: caller, -// proposed_at: get_block_timestamp() -// }); - -// tx_id -// } - -// fn _call(self:@ContractState, function_selector:felt252, calldata:Array)->felt252{ -// get_block_timestamp().into() - -// } - - -// // const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); -// // const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); -// // const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); -// // const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); - - -// } - -// } - From 8c13d3876684721438552d99d527d9a27e115f9f Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 18 Nov 2024 12:46:33 +0530 Subject: [PATCH 6/8] [Feature] added token impl [DONE] --- cairo/.tool-versions | 4 +- cairo/Scarb.lock | 109 +-- cairo/Scarb.toml | 12 +- cairo/src/components/AccessRegistry.cairo | 121 ++-- cairo/src/components/BlackListed.cairo | 12 +- cairo/src/components/Pausable.cairo | 417 +++--------- cairo/src/components/SuperAdmin2Step.cairo | 370 +++++----- cairo/src/contracts/AccessControl.cairo | 230 +++++++ cairo/src/contracts/HSTK.cairo | 229 +++++++ cairo/src/contracts/Multisig.cairo | 412 +++++++++++ cairo/src/contracts/MultisigL2.cairo | 758 +++++++++++---------- cairo/src/interfaces/IaccessRegistry.cairo | 12 +- cairo/src/interfaces/Ipausable.cairo | 1 + cairo/src/lib.cairo | 16 +- 14 files changed, 1596 insertions(+), 1107 deletions(-) create mode 100644 cairo/src/contracts/AccessControl.cairo create mode 100644 cairo/src/contracts/Multisig.cairo diff --git a/cairo/.tool-versions b/cairo/.tool-versions index 45322ff..d141e39 100644 --- a/cairo/.tool-versions +++ b/cairo/.tool-versions @@ -1,2 +1,2 @@ -starknet-foundry 0.27.0 -scarb 2.8.4 +starknet-foundry 0.23.0 +scarb 2.6.3 diff --git a/cairo/Scarb.lock b/cairo/Scarb.lock index 3420067..905bedc 100644 --- a/cairo/Scarb.lock +++ b/cairo/Scarb.lock @@ -11,111 +11,10 @@ dependencies = [ [[package]] name = "openzeppelin" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" -dependencies = [ - "openzeppelin_access", - "openzeppelin_account", - "openzeppelin_finance", - "openzeppelin_governance", - "openzeppelin_introspection", - "openzeppelin_merkle_tree", - "openzeppelin_presets", - "openzeppelin_security", - "openzeppelin_token", - "openzeppelin_upgrades", - "openzeppelin_utils", -] - -[[package]] -name = "openzeppelin_access" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" -dependencies = [ - "openzeppelin_introspection", - "openzeppelin_utils", -] - -[[package]] -name = "openzeppelin_account" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" -dependencies = [ - "openzeppelin_introspection", - "openzeppelin_utils", -] - -[[package]] -name = "openzeppelin_finance" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" -dependencies = [ - "openzeppelin_access", - "openzeppelin_token", -] - -[[package]] -name = "openzeppelin_governance" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" -dependencies = [ - "openzeppelin_access", - "openzeppelin_account", - "openzeppelin_introspection", - "openzeppelin_token", -] - -[[package]] -name = "openzeppelin_introspection" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" - -[[package]] -name = "openzeppelin_merkle_tree" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" - -[[package]] -name = "openzeppelin_presets" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" -dependencies = [ - "openzeppelin_access", - "openzeppelin_account", - "openzeppelin_finance", - "openzeppelin_introspection", - "openzeppelin_token", - "openzeppelin_upgrades", - "openzeppelin_utils", -] - -[[package]] -name = "openzeppelin_security" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" - -[[package]] -name = "openzeppelin_token" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" -dependencies = [ - "openzeppelin_access", - "openzeppelin_account", - "openzeppelin_introspection", - "openzeppelin_utils", -] - -[[package]] -name = "openzeppelin_upgrades" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" - -[[package]] -name = "openzeppelin_utils" -version = "0.19.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628" +version = "0.13.0" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.13.0#978b4e75209da355667d8954d2450e32bd71fe49" [[package]] name = "snforge_std" -version = "0.27.0" -source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.27.0#2d99b7c00678ef0363881ee0273550c44a9263de" +version = "0.23.0" +source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.23.0#f2bff8f796763ada77fe6033ec1b034ceee22abd" diff --git a/cairo/Scarb.toml b/cairo/Scarb.toml index b1ae1eb..092acfc 100644 --- a/cairo/Scarb.toml +++ b/cairo/Scarb.toml @@ -8,12 +8,16 @@ edition = "2023_11" # ... [dependencies] -snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.27.0" } -openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.19.0" } -starknet = "2.8.4" +starknet = "2.6.3" +openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.13.0" } + +[dev-dependencies] +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.23.0" } + + [[target.starknet-contract]] -casm = true sierra = true +casm = true diff --git a/cairo/src/components/AccessRegistry.cairo b/cairo/src/components/AccessRegistry.cairo index c3b6fd5..a3477b6 100644 --- a/cairo/src/components/AccessRegistry.cairo +++ b/cairo/src/components/AccessRegistry.cairo @@ -1,28 +1,30 @@ -//dsdedewded + #[starknet::component] pub mod AccessRegistryComp { use starknet::{get_caller_address,get_block_timestamp}; use starknet::ContractAddress; - use cairo::interfaces::IaccessRegistry::IAccessRegistryComponent; + use cairo::interfaces::IaccessRegistry::IAccessRegistry; // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp::SuperAdminTwoStepImpl; // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp::InternalImpl; // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp; use core::num::traits::Zero; // use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; // use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; - + use openzeppelin_introspection::src5::SRC5Component::InternalImpl as SRC5InternalImpl; + use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; + use openzeppelin_introspection::src5::SRC5Component; #[storage] pub struct Storage { - super_admin:ContractAddress, - pending_admin: ContractAddress, - handover_expires: u64, - total_signers: u64, - signers:LegacyMap::, + pub super_admin: ContractAddress, + pub pending_admin: ContractAddress, + pub signers: LegacyMap::, + pub handover_expires: u64, + pub total_signer: u64, } #[event] - #[derive(Drop, PartialEq, starknet::Event)] + #[derive(Drop,PartialEq, starknet::Event)] pub enum Event { SignerAdded: SignerAdded, SignerRemoved: SignerRemoved, @@ -31,39 +33,33 @@ pub mod AccessRegistryComp { SuperOwnershipTransferStarted: SuperOwnershipTransferStarted } - #[derive(Drop, PartialEq, starknet::Event)] + #[derive(Drop,PartialEq, starknet::Event)] pub struct SignerAdded { #[key] - pub signer: ContractAddress + signer: ContractAddress } - #[derive(Drop, PartialEq, starknet::Event)] + #[derive(Drop,PartialEq, starknet::Event)] pub struct SignerRemoved { #[key] - pub signer: ContractAddress + signer: ContractAddress } - #[derive(Drop, PartialEq, starknet::Event)] + #[derive(Drop,PartialEq, starknet::Event)] pub struct SignerRenounced { - #[key] - pub from: ContractAddress, - #[key] - pub to: ContractAddress + from: ContractAddress, + to: ContractAddress } - #[derive(Drop, PartialEq, starknet::Event)] + #[derive(Drop,PartialEq, starknet::Event)] pub struct SuperOwnershipTransferred { - #[key] - pub previous_super_admin: ContractAddress, - #[key] - pub new_super_admin: ContractAddress, + previous_super_admin: ContractAddress, + new_super_admin: ContractAddress, } - #[derive(Drop, PartialEq, starknet::Event)] + #[derive(Drop,PartialEq, starknet::Event)] pub struct SuperOwnershipTransferStarted { - #[key] - pub previous_super_admin: ContractAddress, - #[key] - pub new_super_admin: ContractAddress, + previous_super_admin: ContractAddress, + new_super_admin: ContractAddress, } pub mod Error { @@ -75,23 +71,21 @@ pub mod AccessRegistryComp { pub const NOT_OWNER: felt252 = 'Caller is not super admin'; pub const NOT_PENDING_OWNER: felt252 = 'Caller not pending super admin'; pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; - pub const ZERO_ADDRESS_OWNER: felt252 = 'Calldata consist zero address'; pub const HANDOVER_EXPIRED: felt252 = 'Super Admin Ownership expired'; } - #[embeddable_as(AccessRegistryImpl)] - pub impl AccessRegisty< - TContractState, - +HasComponent, - // impl SuperAdminTwoStepImpl: SuperAdminTwoStepComp::HasComponent, - +Drop - > of IAccessRegistryComponent> { + #[embeddable_as(AccessRegistry)] + impl AccessRegistyImpl< + TContractState,+HasComponent,+Drop, + +SRC5Component::HasComponent, + > of super::IAccessRegistry> { + fn is_signer(self: @ComponentState, account: ContractAddress) -> bool { self.signers.read(account) } - fn total_signer(self:@ComponentState)->u64{ - self.total_signers.read() + fn get_total_signer(self:@ComponentState)->u64{ + self.total_signer.read() } fn add_signer(ref self: ComponentState, new_signer: ContractAddress) { @@ -101,7 +95,7 @@ pub mod AccessRegistryComp { // let super_admin_comp = get_dep_component!(@self, SuperAdminTwoStepImpl); self.assert_only_super_admin(); self.signers.write(new_signer, true); - self.total_signers.write(self.total_signers.read() + 1); + self.total_signer.write(self.total_signer.read() + 1); self.emit(SignerAdded { signer: new_signer }); } @@ -116,7 +110,7 @@ pub mod AccessRegistryComp { self.assert_only_super_admin(); self.signers.write(existing_owner, false); - self.total_signers.write(self.total_signers.read() - 1); + self.total_signer.write(self.total_signer.read() - 1); self.emit(SignerRemoved { signer: existing_owner }); } @@ -142,24 +136,7 @@ pub mod AccessRegistryComp { self._renounce_signership(caller,super_admin); } - // fn initializer(ref self: ComponentState, super_admin: ContractAddress) { - - // .initializer(super_admin); - // self.total_signers.write(1); - // self.signers.write(super_admin, true); - // } - - // fn initializer( - // ref self: ComponentState, - // parent_storage: &mut Storage - // ) { - // let mut super_admin_comp = get_dep_component_mut!(ref self, SuperAdminTwoStepImpl); - // super_admin_comp.initializer(parent_storage.super_admin); - // self.total_signers.write(1); - // self.signers.write(parent_storage.super_admin, true); - // } - - fn super_admin(self: @ComponentState) -> ContractAddress { + fn get_super_admin(self: @ComponentState) -> ContractAddress { self.super_admin.read() } @@ -196,11 +173,22 @@ pub mod AccessRegistryComp { } #[generate_trait] - pub impl InternalImp< - TContractState, - +HasComponent, - +Drop + pub impl InternalImpl< + TContractState, +HasComponent,+Drop, + impl SRC5: SRC5Component::HasComponent, > of InternalTrait { + + /// Sets the contract's initial super_admin. + /// + /// This function should be called at construction time. + fn initializer(ref self: ComponentState, super_admin: ContractAddress) { + self.super_admin(super_admin); + self.total_signer.write(1); + self.signers.write(super_admin, true); + let mut src5_component = get_dep_component_mut!(ref self, SRC5); + src5_component.register_interface(IaccessRegistry::IACCESSCONTROL_ID); + } + fn _renounce_signership( ref self: ComponentState, _from: ContractAddress, _to: ContractAddress ) { @@ -209,15 +197,6 @@ pub mod AccessRegistryComp { self.emit(SignerRenounced { from: _from, to: _to }); } - /// Sets the contract's initial super_admin. - /// - /// This function should be called at construction time. - fn initializer(ref self: ComponentState, super_admin: ContractAddress) { - self._transfer_super_adminship(super_admin); - self.total_signers.write(1); - self.signers.write(super_admin, true); - } - /// Panics if called by any account other than the super_admin. Use this /// to restrict access to certain functions to the super_admin. fn assert_only_super_admin(self: @ComponentState) { diff --git a/cairo/src/components/BlackListed.cairo b/cairo/src/components/BlackListed.cairo index f3cc3dc..c09ce6f 100644 --- a/cairo/src/components/BlackListed.cairo +++ b/cairo/src/components/BlackListed.cairo @@ -3,7 +3,7 @@ use core::traits::Into; use core::option::OptionTrait; #[starknet::component] -mod BlackListedComp { +pub mod BlackListedComp { use core::num::traits::zero::Zero; use cairo::interfaces::IblackListed::IBlackListedComponent; use starknet::{ContractAddress, get_caller_address}; @@ -17,19 +17,19 @@ mod BlackListedComp { #[event] #[derive(Drop, starknet::Event)] - enum Event { + pub enum Event { NewAccountBlackListed: NewAccountBlackListed, RemovedAccountBlackListed: RemovedAccountBlackListed, } #[derive(Drop, starknet::Event)] - struct NewAccountBlackListed { + pub struct NewAccountBlackListed { #[key] blacklisted_account: ContractAddress } #[derive(Drop, starknet::Event)] - struct RemovedAccountBlackListed { + pub struct RemovedAccountBlackListed { #[key] removed_account: ContractAddress } @@ -65,9 +65,9 @@ mod BlackListedComp { } #[generate_trait] - impl InternalFunctions< + pub impl InternalImpl< TContractState, +HasComponent - > of InternalFunctionsTrait { + > of InternalTrait { fn initializer(ref self: ComponentState, multi_sig: ContractAddress) { assert(multi_sig.is_zero(), errors::ZERO_ADDRESS); self.multi_sig.write(multi_sig); diff --git a/cairo/src/components/Pausable.cairo b/cairo/src/components/Pausable.cairo index 3d3c9ee..1aafa32 100644 --- a/cairo/src/components/Pausable.cairo +++ b/cairo/src/components/Pausable.cairo @@ -1,390 +1,125 @@ -// // // Define the pause states using an enum -// // #[starknet::component] -// // pub mod Pausable { -// // use cairo_starknet::helpers::constants; -// // use cairo_starknet::interfaces::Ipausable::IPausable; - -// // #[derive(Drop, Copy, Serde)] -// // pub enum PauseState { -// // Active, -// // PartialPause, -// // FullPause -// // } - -// // #[storage] -// // struct Storage { -// // current_state: PauseState -// // } - -// // #[event] -// // #[derive(Drop, starknet::Event)] -// // enum Event { -// // PauseStateChanged: PauseStateChanged, -// // } - -// // #[derive(Drop, starknet::Event)] -// // struct PauseStateChanged { -// // new_state: PauseState, -// // } - -// // #[derive(Drop, PartialEq)] -// // enum PausableError { -// // EnforcedPause, -// // EnforcedPartialPause, -// // InvalidStateChange, -// // } - -// // fn panic_with_felt252(err: felt252) { -// // core::panic_with_felt252(err) -// // } - -// // impl PausableErrorIntoFelt252 of Into { -// // fn into(self: PausableError) -> felt252 { -// // match self { -// // PausableError::EnforcedPause => 'Contract is fully paused', -// // PausableError::EnforcedPartialPause => 'Contract is partially paused', -// // PausableError::InvalidStateChange => 'Invalid state change' -// // } -// // } -// // } - -// // #[embeddable_as(Pausable)] -// // impl PausableImpl< -// // TContractState, -// // impl TContractStateDestruct: Drop, -// // impl TContractStateComponent: HasComponent -// // > of IPausable> { -// // fn get_current_state(self: @ComponentState) -> PauseState { -// // self.current_state.read() -// // } - -// // fn is_active(self: @ComponentState) -> bool { -// // match self.current_state.read() { -// // PauseState::Active => true, -// // _ => false -// // } -// // } - -// // fn is_partial_paused(self: @ComponentState) -> bool { -// // match self.current_state.read() { -// // PauseState::PartialPause => true, -// // _ => false -// // } -// // } - -// // fn is_full_paused(self: @ComponentState) -> bool { -// // match self.current_state.read() { -// // PauseState::FullPause => true, -// // _ => false -// // } -// // } -// // } - -// // #[generate_trait] -// // impl InternalFunctions< -// // TContractState, -// // impl TContractStateDestruct: Drop, -// // impl TContractStateComponent: HasComponent -// // > of InternalFunctionsTrait { -// // fn initializer(ref self: ComponentState) { -// // self.current_state.write(PauseState::Active); -// // } - -// // fn _require_active(self: @ComponentState) { -// // let current_state = self.current_state.read(); -// // match current_state { -// // PauseState::Active => {}, -// // PauseState::PartialPause => { -// // panic_with_felt252(PausableError::EnforcedPartialPause.into()) -// // }, -// // PauseState::FullPause => { -// // panic_with_felt252(PausableError::EnforcedPause.into()) -// // } -// // } -// // } - -// // fn _require_active_or_partial(self: @ComponentState) { -// // let current_state = self.current_state.read(); -// // match current_state { -// // PauseState::Active => {}, -// // PauseState::PartialPause => {}, -// // PauseState::FullPause => { -// // panic_with_felt252(PausableError::EnforcedPause.into()) -// // } -// // } -// // } - -// // fn _update_operational_state( -// // ref self: ComponentState, -// // new_state: PauseState -// // ) { -// // self.current_state.write(new_state); - -// // // Emit state change event -// // self.emit(Event::PauseStateChanged( -// // PauseStateChanged { new_state } -// // )); -// // } -// // } -// // } - -// // #[starknet::component] -// // pub mod Pausable { -// // use starknet::ContractAddress; -// // use cairo_starknet::helpers::constants; -// // use cairo_starknet::interfaces::Ipausable::IPausable; - -// // #[derive(Drop, Copy, Serde)] -// // pub enum PauseState { -// // Active, -// // PartialPause, -// // FullPause -// // } - -// // #[storage] -// // struct Storage { -// // current_state: PauseState -// // } - -// // #[event] -// // #[derive(Drop, starknet::Event)] -// // enum Event { -// // PauseStateChanged: PauseStateChanged, -// // } - -// // #[derive(Drop, starknet::Event)] -// // struct PauseStateChanged { -// // new_state: PauseState, -// // } - -// // #[derive(Drop, PartialEq)] -// // enum PausableError { -// // EnforcedPause, -// // EnforcedPartialPause, -// // InvalidStateChange, -// // } - -// // fn panic_with_felt252(err: felt252) { -// // core::panic_with_felt252(err) -// // } - -// // impl PausableErrorIntoFelt252 of Into { -// // fn into(self: PausableError) -> felt252 { -// // match self { -// // PausableError::EnforcedPause => 'Contract is fully paused', -// // PausableError::EnforcedPartialPause => 'Contract is partially paused', -// // PausableError::InvalidStateChange => 'Invalid state change' -// // } -// // } -// // } - -// // #[embeddable_as(Pausable)] -// // impl PausableImpl< -// // TContractState, -// // impl TContractStateDestruct: Drop, -// // impl TContractStateComponent: HasComponent -// // > of IPausable> { -// // fn get_current_state(self: @ComponentState) -> PauseState { -// // let state = self.current_state.read(); -// // state -// // } - -// // fn is_active(self: @ComponentState) -> bool { -// // match self.get_current_state() { -// // PauseState::Active => true, -// // _ => false -// // } -// // } - -// // fn is_partial_paused(self: @ComponentState) -> bool { -// // match self.get_current_state() { -// // PauseState::PartialPause => true, -// // _ => false -// // } -// // } - -// // fn is_full_paused(self: @ComponentState) -> bool { -// // match self.get_current_state() { -// // PauseState::FullPause => true, -// // _ => false -// // } -// // } -// // } - -// // #[generate_trait] -// // impl InternalFunctions< -// // TContractState, -// // impl TContractStateDestruct: Drop, -// // impl TContractStateComponent: HasComponent -// // > of InternalFunctionsTrait { -// // fn initializer(ref self: ComponentState) { -// // self.current_state.write(PauseState::Active); -// // } - -// // fn _require_active(self: @ComponentState) { -// // match self.get_current_state() { -// // PauseState::Active => {}, -// // PauseState::PartialPause => { -// // panic_with_felt252(PausableError::EnforcedPartialPause.into()) -// // }, -// // PauseState::FullPause => { -// // panic_with_felt252(PausableError::EnforcedPause.into()) -// // } -// // } -// // } - -// // fn _require_active_or_partial(self: @ComponentState) { -// // match self.get_current_state() { -// // PauseState::Active => {}, -// // PauseState::PartialPause => {}, -// // PauseState::FullPause => { -// // panic_with_felt252(PausableError::EnforcedPause.into()) -// // } -// // } -// // } - -// // fn _update_operational_state( -// // ref self: ComponentState, -// // new_state: PauseState -// // ) { -// // self.current_state.write(new_state); - -// // // Emit state change event -// // self.emit(Event::PauseStateChanged( -// // PauseStateChanged { new_state } -// // )); -// // } -// // } -// // } - // use starknet::ContractAddress; -// use core::starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; +// use starknet::{get_caller_address, get_contract_address}; +// use starknet::storage_access::StorageAccess; +// use starknet::storage_access::StorageBaseAddress; +// use starknet::SyscallResult; // #[starknet::interface] -// trait IPausable { +// pub trait IPausable { // fn get_current_state(self: @TContractState) -> PauseState; // fn is_active(self: @TContractState) -> bool; // fn is_partial_paused(self: @TContractState) -> bool; // fn is_full_paused(self: @TContractState) -> bool; // } -// #[derive(Drop, Copy, Serde)] +// #[derive(Drop, Copy, Serde, PartialEq)] +// #[repr(felt252)] // pub enum PauseState { // Active, // PartialPause, // FullPause // } +// // Implement StorageAccess for PauseState +// impl StorageAccessPauseState of StorageAccess { +// fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult { +// let val = StorageAccess::::read(address_domain, base)?; +// match val { +// 0 => Result::Ok(PauseState::Active), +// 1 => Result::Ok(PauseState::PartialPause), +// 2 => Result::Ok(PauseState::FullPause), +// _ => Result::Err(array!['Invalid PauseState value']) +// } +// } + +// fn write(address_domain: u32, base: StorageBaseAddress, value: PauseState) -> SyscallResult<()> { +// let val = match value { +// PauseState::Active => 0, +// PauseState::PartialPause => 1, +// PauseState::FullPause => 2, +// }; +// StorageAccess::::write(address_domain, base, val) +// } + +// fn size() -> u8 { +// 1 +// } +// } + // #[starknet::component] -// pub mod Pausable { +// pub mod pausable_component { // use super::{PauseState, IPausable}; -// use starknet::ContractAddress; -// use core::starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; +// use starknet::{get_caller_address, ContractAddress}; // #[storage] // struct Storage { -// current_state: PauseState +// current_state: PauseState, // } // #[event] // #[derive(Drop, starknet::Event)] -// enum Event { -// PauseStateChanged: PauseStateChanged, +// pub enum Event { +// PauseStateChanged: PauseStateChanged // } // #[derive(Drop, starknet::Event)] -// struct PauseStateChanged { -// new_state: PauseState, +// pub struct PauseStateChanged { +// #[key] +// pub caller: ContractAddress, +// pub new_state: PauseState, // } -// #[derive(Drop, PartialEq)] -// enum PausableError { -// EnforcedPause, -// EnforcedPartialPause, -// InvalidStateChange, +// #[generate_trait] +// pub trait InternalTrait { +// fn _assert_active(self: @ComponentState); +// fn _assert_not_full_paused(self: @ComponentState); +// fn _update_state(ref self: ComponentState, new_state: PauseState); +// fn initializer(ref self: ComponentState); // } -// fn panic_with_felt252(err: felt252) { -// core::panic_with_felt252(err) -// } +// #[generate_trait] +// impl InternalImpl of InternalTrait { +// fn _assert_active(self: @ComponentState) { +// let state = self.current_state.read().unwrap(); +// assert(state == PauseState::Active, 'Contract must be active'); +// } -// impl PausableErrorIntoFelt252 of Into { -// fn into(self: PausableError) -> felt252 { -// match self { -// PausableError::EnforcedPause => 'Contract is fully paused', -// PausableError::EnforcedPartialPause => 'Contract is partially paused', -// PausableError::InvalidStateChange => 'Invalid state change' -// } +// fn _assert_not_full_paused(self: @ComponentState) { +// let state = self.current_state.read().unwrap(); +// assert(state != PauseState::FullPause, 'Contract must not be fully paused'); +// } + +// fn _update_state(ref self: ComponentState, new_state: PauseState) { +// self.current_state.write(new_state).unwrap(); +// self.emit(Event::PauseStateChanged(PauseStateChanged { +// caller: get_caller_address(), +// new_state +// })); +// } + +// fn initializer(ref self: ComponentState) { +// self.current_state.write(PauseState::Active).unwrap(); // } // } -// #[embeddable_as(Pausable)] +// #[embeddable_as(IPausableImpl)] // impl PausableImpl< -// TContractState, -// impl TContractStateDestruct: Drop, -// impl TContractStateComponent: HasComponent +// TContractState, impl TContractStateHasComponent: HasComponent // > of IPausable> { // fn get_current_state(self: @ComponentState) -> PauseState { -// let current_state = StorageMemberAccessTrait::::read(self.current_state.address()); -// current_state +// self.current_state.read().unwrap() // } // fn is_active(self: @ComponentState) -> bool { -// match self.get_current_state() { -// PauseState::Active => true, -// _ => false -// } +// self.current_state.read().unwrap() == PauseState::Active // } // fn is_partial_paused(self: @ComponentState) -> bool { -// match self.get_current_state() { -// PauseState::PartialPause => true, -// _ => false -// } +// self.current_state.read().unwrap() == PauseState::PartialPause // } // fn is_full_paused(self: @ComponentState) -> bool { -// match self.get_current_state() { -// PauseState::FullPause => true, -// _ => false -// } +// self.current_state.read().unwrap() == PauseState::FullPause // } // } - -// #[generate_trait] -// impl InternalFunctions< -// TContractState, -// impl TContractStateDestruct: Drop, -// impl TContractStateComponent: HasComponent -// > of InternalFunctionsTrait { -// fn initializer(ref self: ComponentState) { -// StorageMemberAccessTrait::::write( -// self.current_state.address(), -// PauseState::Active -// ); -// } - -// fn _require_active(self: @ComponentState) { -// match self.get_current_state() { -// PauseState::Active => {}, -// PauseState::PartialPause => { -// panic_with_felt252(PausableError::EnforcedPartialPause.into()) -// }, -// PauseState::FullPause => { -// panic_with_felt252(PausableError::EnforcedPause.into()) -// } -// } -// } - -// fn _require_active_or_partial(self: @ComponentState) { -// match self.get_current_state() { -// PauseState::Active => {}, -// PauseState::PartialPause => {}, -// PauseState::FullPause => { -// panic_with_felt252(PausableError::EnforcedPause.into()) -// } -// } -// } - -// fn _update_operational_ - +// } \ No newline at end of file diff --git a/cairo/src/components/SuperAdmin2Step.cairo b/cairo/src/components/SuperAdmin2Step.cairo index 369353d..d141029 100644 --- a/cairo/src/components/SuperAdmin2Step.cairo +++ b/cairo/src/components/SuperAdmin2Step.cairo @@ -1,185 +1,185 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.19.0 (access/ownable/ownable.cairo) - -/// # Ownable Component -/// -/// The Ownable component provides a basic access control mechanism, where -/// there is an account (an super_admin) that can be granted exclusive access to -/// specific functions. -/// -/// The initial super_admin can be set by using the `initializer` function in -/// construction time. This can later be changed with `transfer_super_adminship`. -/// -/// The component also offers functionality for a two-step super_adminship -/// transfer where the new super_admin first has to accept their super_adminship to -/// finalize the transfer. -#[starknet::component] -pub mod SuperAdminTwoStepComp { - use core::num::traits::Zero; - use cairo::interfaces::IsuperAdmin2Step::ISuperAdminTwoStep; - // use cairo_starknet::interfaces::IsuperAdmin2Step; - use cairo::interfaces::IsuperAdmin2Step; - - use starknet::ContractAddress; - use starknet::{get_caller_address, get_block_timestamp}; - - #[storage] - pub struct Storage { - pub super_admin: ContractAddress, - pub pending_admin: ContractAddress, - pub handover_expires: u64 - } - - #[event] - #[derive(Drop, PartialEq, starknet::Event)] - pub enum Event { - SuperOwnershipTransferred: SuperOwnershipTransferred, - SuperOwnershipTransferStarted: SuperOwnershipTransferStarted - } - - #[derive(Drop, PartialEq, starknet::Event)] - pub struct SuperOwnershipTransferred { - #[key] - pub previous_super_admin: ContractAddress, - #[key] - pub new_super_admin: ContractAddress, - } - - #[derive(Drop, PartialEq, starknet::Event)] - pub struct SuperOwnershipTransferStarted { - #[key] - pub previous_super_admin: ContractAddress, - #[key] - pub new_super_admin: ContractAddress, - } - - pub mod Errors { - pub const NOT_OWNER: felt252 = 'Caller is not super admin'; - pub const NOT_PENDING_OWNER: felt252 = 'Caller not pending super admin'; - pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; - pub const ZERO_ADDRESS_OWNER: felt252 = 'Calldata consist zero address'; - pub const HANDOVER_EXPIRED: felt252 = 'Super Admin Ownership expired'; - } - - /// Adds support for two step super_adminship transfer. - #[embeddable_as(SuperAdminTwoStepImpl)] - pub impl SuperAdminTwoStep< - TContractState, +HasComponent, +Drop - > of IsuperAdmin2Step::ISuperAdminTwoStep> { - /// Returns the address of the current super_admin. - fn super_admin(self: @ComponentState) -> ContractAddress { - self.super_admin.read() - } - - /// Returns the address of the pending super_admin. - fn pending_super_admin(self: @ComponentState) -> ContractAddress { - self.pending_admin.read() - } - - //Returns the handover expiry of the pending super_admin - fn super_handover_expires_at(self: @ComponentState) -> u64 { - self.handover_expires.read() - } - - - /// Starts the two-step super_adminship transfer process by setting the pending super_admin. - /// - /// Requirements: - /// - /// - The caller is the contract super_admin. - /// - /// Emits an `OwnershipTransferStarted` event. - fn transfer_super_adminship( - ref self: ComponentState, new_super_admin: ContractAddress - ) { - self.assert_only_super_admin(); - self._propose_super_admin(new_super_admin); - } - - /// Returns the time for which handover is valid for pending super_admin. - fn super_admin_ownership_valid_for(self: @ComponentState) -> u64 { - 72 * 3600 - } - } - - #[generate_trait] - pub impl InternalImpl< - TContractState, +HasComponent - > of InternalTrait { - /// Sets the contract's initial super_admin. - /// - /// This function should be called at construction time. - fn initializer(ref self: ComponentState, super_admin: ContractAddress) { - self._transfer_super_adminship(super_admin); - } - - /// Panics if called by any account other than the super_admin. Use this - /// to restrict access to certain functions to the super_admin. - fn assert_only_super_admin(self: @ComponentState) { - let super_admin = self.super_admin.read(); - let caller = get_caller_address(); - assert(!caller.is_zero(), Errors::ZERO_ADDRESS_CALLER); - assert(caller == super_admin, Errors::NOT_OWNER); - } - - /// Finishes the two-step super_adminship transfer process by accepting the super_adminship. - /// Can only be called by the pending super_admin. - /// - /// Requirements: - /// - /// - The caller is the pending super_admin. - /// - /// Emits an `OwnershipTransferred` event. - fn _accept_super_adminship(ref self: ComponentState) { - let caller = get_caller_address(); - let pending_super_admin = self.pending_admin.read(); - let super_adminship_expires_at: u64 = self.handover_expires.read(); - assert(caller == pending_super_admin, Errors::NOT_PENDING_OWNER); - assert(get_block_timestamp() <= super_adminship_expires_at, Errors::HANDOVER_EXPIRED); - self._transfer_super_adminship(pending_super_admin); - } - - /// Transfers super_adminship of the contract to a new address and resets - /// the pending super_admin to the zero address. - /// - /// Internal function without access restriction. - /// - /// Emits an `OwnershipTransferred` event. - fn _transfer_super_adminship( - ref self: ComponentState, new_super_admin: ContractAddress - ) { - self.pending_admin.write(Zero::zero()); - self.handover_expires.write(0); - - let previous_super_admin: ContractAddress = self.super_admin.read(); - self.super_admin.write(new_super_admin); - self - .emit( - SuperOwnershipTransferred { - previous_super_admin: previous_super_admin, new_super_admin: new_super_admin - } - ); - } - - /// Sets a new pending super_admin. - /// - /// Internal function without access restriction. - /// - /// Emits an `OwnershipTransferStarted` event. - fn _propose_super_admin( - ref self: ComponentState, new_super_admin: ContractAddress - ) { - let previous_super_admin = self.super_admin.read(); - self.pending_admin.write(new_super_admin); - let super_adminship_expires_at = get_block_timestamp() - + 72 * 3600; - self.handover_expires.write(super_adminship_expires_at); - self - .emit( - SuperOwnershipTransferStarted { - previous_super_admin: previous_super_admin, new_super_admin: new_super_admin - } - ); - } - } -} +// // SPDX-License-Identifier: MIT +// // OpenZeppelin Contracts for Cairo v0.19.0 (access/ownable/ownable.cairo) + +// /// # Ownable Component +// /// +// /// The Ownable component provides a basic access control mechanism, where +// /// there is an account (an super_admin) that can be granted exclusive access to +// /// specific functions. +// /// +// /// The initial super_admin can be set by using the `initializer` function in +// /// construction time. This can later be changed with `transfer_super_adminship`. +// /// +// /// The component also offers functionality for a two-step super_adminship +// /// transfer where the new super_admin first has to accept their super_adminship to +// /// finalize the transfer. +// #[starknet::component] +// pub mod SuperAdminTwoStepComp { +// use core::num::traits::Zero; +// use cairo::interfaces::IsuperAdmin2Step::ISuperAdminTwoStep; +// // use cairo_starknet::interfaces::IsuperAdmin2Step; +// use cairo::interfaces::IsuperAdmin2Step; + +// use starknet::ContractAddress; +// use starknet::{get_caller_address, get_block_timestamp}; + +// #[storage] +// pub struct Storage { +// pub super_admin: ContractAddress, +// pub pending_admin: ContractAddress, +// pub handover_expires: u64 +// } + +// #[event] +// #[derive(Drop, PartialEq, starknet::Event)] +// pub enum Event { +// SuperOwnershipTransferred: SuperOwnershipTransferred, +// SuperOwnershipTransferStarted: SuperOwnershipTransferStarted +// } + +// #[derive(Drop, PartialEq, starknet::Event)] +// pub struct SuperOwnershipTransferred { +// #[key] +// pub previous_super_admin: ContractAddress, +// #[key] +// pub new_super_admin: ContractAddress, +// } + +// #[derive(Drop, PartialEq, starknet::Event)] +// pub struct SuperOwnershipTransferStarted { +// #[key] +// pub previous_super_admin: ContractAddress, +// #[key] +// pub new_super_admin: ContractAddress, +// } + +// pub mod Errors { +// pub const NOT_OWNER: felt252 = 'Caller is not super admin'; +// pub const NOT_PENDING_OWNER: felt252 = 'Caller not pending super admin'; +// pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; +// pub const ZERO_ADDRESS_OWNER: felt252 = 'Calldata consist zero address'; +// pub const HANDOVER_EXPIRED: felt252 = 'Super Admin Ownership expired'; +// } + +// /// Adds support for two step super_adminship transfer. +// #[embeddable_as(SuperAdminTwoStepImpl)] +// pub impl SuperAdminTwoStep< +// TContractState, +HasComponent, +Drop +// > of IsuperAdmin2Step::ISuperAdminTwoStep> { +// /// Returns the address of the current super_admin. +// fn super_admin(self: @ComponentState) -> ContractAddress { +// self.super_admin.read() +// } + +// /// Returns the address of the pending super_admin. +// fn pending_super_admin(self: @ComponentState) -> ContractAddress { +// self.pending_admin.read() +// } + +// //Returns the handover expiry of the pending super_admin +// fn super_handover_expires_at(self: @ComponentState) -> u64 { +// self.handover_expires.read() +// } + + +// /// Starts the two-step super_adminship transfer process by setting the pending super_admin. +// /// +// /// Requirements: +// /// +// /// - The caller is the contract super_admin. +// /// +// /// Emits an `OwnershipTransferStarted` event. +// fn transfer_super_adminship( +// ref self: ComponentState, new_super_admin: ContractAddress +// ) { +// self.assert_only_super_admin(); +// self._propose_super_admin(new_super_admin); +// } + +// /// Returns the time for which handover is valid for pending super_admin. +// fn super_admin_ownership_valid_for(self: @ComponentState) -> u64 { +// 72 * 3600 +// } +// } + +// #[generate_trait] +// pub impl InternalImpl< +// TContractState, +HasComponent +// > of InternalTrait { +// /// Sets the contract's initial super_admin. +// /// +// /// This function should be called at construction time. +// fn initializer(ref self: ComponentState, super_admin: ContractAddress) { +// self._transfer_super_adminship(super_admin); +// } + +// /// Panics if called by any account other than the super_admin. Use this +// /// to restrict access to certain functions to the super_admin. +// fn assert_only_super_admin(self: @ComponentState) { +// let super_admin = self.super_admin.read(); +// let caller = get_caller_address(); +// assert(!caller.is_zero(), Errors::ZERO_ADDRESS_CALLER); +// assert(caller == super_admin, Errors::NOT_OWNER); +// } + +// /// Finishes the two-step super_adminship transfer process by accepting the super_adminship. +// /// Can only be called by the pending super_admin. +// /// +// /// Requirements: +// /// +// /// - The caller is the pending super_admin. +// /// +// /// Emits an `OwnershipTransferred` event. +// fn _accept_super_adminship(ref self: ComponentState) { +// let caller = get_caller_address(); +// let pending_super_admin = self.pending_admin.read(); +// let super_adminship_expires_at: u64 = self.handover_expires.read(); +// assert(caller == pending_super_admin, Errors::NOT_PENDING_OWNER); +// assert(get_block_timestamp() <= super_adminship_expires_at, Errors::HANDOVER_EXPIRED); +// self._transfer_super_adminship(pending_super_admin); +// } + +// /// Transfers super_adminship of the contract to a new address and resets +// /// the pending super_admin to the zero address. +// /// +// /// Internal function without access restriction. +// /// +// /// Emits an `OwnershipTransferred` event. +// fn _transfer_super_adminship( +// ref self: ComponentState, new_super_admin: ContractAddress +// ) { +// self.pending_admin.write(Zero::zero()); +// self.handover_expires.write(0); + +// let previous_super_admin: ContractAddress = self.super_admin.read(); +// self.super_admin.write(new_super_admin); +// self +// .emit( +// SuperOwnershipTransferred { +// previous_super_admin: previous_super_admin, new_super_admin: new_super_admin +// } +// ); +// } + +// /// Sets a new pending super_admin. +// /// +// /// Internal function without access restriction. +// /// +// /// Emits an `OwnershipTransferStarted` event. +// fn _propose_super_admin( +// ref self: ComponentState, new_super_admin: ContractAddress +// ) { +// let previous_super_admin = self.super_admin.read(); +// self.pending_admin.write(new_super_admin); +// let super_adminship_expires_at = get_block_timestamp() +// + 72 * 3600; +// self.handover_expires.write(super_adminship_expires_at); +// self +// .emit( +// SuperOwnershipTransferStarted { +// previous_super_admin: previous_super_admin, new_super_admin: new_super_admin +// } +// ); +// } +// } +// } diff --git a/cairo/src/contracts/AccessControl.cairo b/cairo/src/contracts/AccessControl.cairo new file mode 100644 index 0000000..d16d321 --- /dev/null +++ b/cairo/src/contracts/AccessControl.cairo @@ -0,0 +1,230 @@ +#[starknet::component] +pub mod AccessControlComponent{ + use starknet::{ContractAddress,get_block_timestamp,get_caller_address}; + use cairo::interfaces::IaccessRegistry::IAccessRegistry; + use core::num::traits::Zero; + + #[storage] + pub struct Storage{ + pub Super_admin: ContractAddress, + pub Pending_admin: ContractAddress, + pub Signers: LegacyMap::, + pub Handover_expires: u64, + pub Total_signer: u64, + } + + #[event] + #[derive(Drop,PartialEq, starknet::Event)] + pub enum Event{ + SignerAdded: SignerAdded, + SignerRemoved: SignerRemoved, + SuperOwnershipTransferred: SuperOwnershipTransferred, + SuperOwnershipTransferStarted: SuperOwnershipTransferStarted + } + + #[derive(Drop,PartialEq, starknet::Event)] + pub struct SignerAdded { + pub signer: ContractAddress + } + + #[derive(Drop,PartialEq, starknet::Event)] + pub struct SignerRemoved { + pub signer: ContractAddress + } + #[derive(Drop,PartialEq, starknet::Event)] + pub struct SuperOwnershipTransferred { + pub previous_super_admin: ContractAddress, + pub new_super_admin: ContractAddress, + } + + #[derive(Drop,PartialEq, starknet::Event)] + pub struct SuperOwnershipTransferStarted { + pub previous_super_admin: ContractAddress, + pub new_super_admin: ContractAddress, + } + + pub mod Errors { + pub const ZERO_ADDRESS: felt252 = 'Zero Address'; + pub const SuperAdminIsRestricted: felt252 = 'Super Admin Is Restricted'; + pub const Already_Signer: felt252 = 'Already a Signer'; + pub const SuperAdminCannotRemoved: felt252 = 'Super Admin Cannot Removed'; + pub const NonExistingSigner: felt252 = 'Non Existing Signer'; + pub const NOT_OWNER: felt252 = 'Caller is not super admin'; + pub const NOT_PENDING_OWNER: felt252 = 'Caller not pending super admin'; + pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; + pub const HANDOVER_EXPIRED: felt252 = 'Super Admin Ownership expired'; + } + + #[embeddable_as(AccessControlImpl)] + impl AccessControl< + TContractState, + +HasComponent, + +Drop + > of IAccessRegistry>{ + + fn is_signer(self: @ComponentState, account: ContractAddress)-> bool{ + self.Signers.read(account) + } + fn get_total_signer(self:@ComponentState)->u64{ + self.Total_signer.read() + } + fn add_signer(ref self: ComponentState, new_signer: ContractAddress) { + assert(!new_signer.is_zero(), Errors::ZERO_ADDRESS); + assert(!self.Signers.read(new_signer), Errors::Already_Signer); + + // let super_admin_comp = get_dep_component!(@self, SuperAdminTwoStepImpl); + self.assert_only_super_admin(); + self.Signers.write(new_signer, true); + self.Total_signer.write(self.Total_signer.read() + 1); + self.emit(SignerAdded { signer: new_signer }); + } + + fn remove_signer( + ref self: ComponentState, existing_owner: ContractAddress + ) { + assert(!existing_owner.is_zero(), Errors::ZERO_ADDRESS); + assert(self.Signers.read(existing_owner), Errors::NonExistingSigner); + + let super_admin: ContractAddress = self.Super_admin.read(); + assert(existing_owner != super_admin, Errors::SuperAdminCannotRemoved); + self.assert_only_super_admin(); + + self.Signers.write(existing_owner, false); + self.Total_signer.write(self.Total_signer.read() - 1); + + self.emit(SignerRemoved { signer: existing_owner }); + } + fn renounce_signership(ref self: ComponentState, signer: ContractAddress) { + assert(!signer.is_zero(), Errors::ZERO_ADDRESS); //check for zero address + + let caller: ContractAddress = get_caller_address(); + assert(self.Signers.read(caller), Errors::NonExistingSigner); //only be calleable by signer + assert( + !self.Signers.read(signer), Errors::Already_Signer + ); //new signer cannot be existing signer + + let super_admin: ContractAddress = self.Super_admin.read(); + assert(caller != super_admin, Errors::SuperAdminCannotRemoved); //signer cannot be remove + // check it needs to be existing owner + self._renounce_signership(caller, signer); + } + + fn accept_super_adminship(ref self: ComponentState){ + let caller: ContractAddress = get_caller_address(); + let super_admin:ContractAddress = self.Super_admin.read(); + self._accept_super_adminship(); + self._renounce_signership(caller,super_admin); + } + fn get_super_admin(self: @ComponentState) -> ContractAddress { + self.Super_admin.read() + } + + /// Returns the address of the pending super_admin. + fn pending_super_admin(self: @ComponentState) -> ContractAddress { + self.Pending_admin.read() + } + + //Returns the handover expiry of the pending super_admin + fn super_handover_expires_at(self: @ComponentState) -> u64 { + self.Handover_expires.read() + } + + + /// Starts the two-step super_adminship transfer process by setting the pending super_admin. + /// + /// Requirements: + /// + /// - The caller is the contract super_admin. + /// + /// Emits an `OwnershipTransferStarted` event. + fn transfer_super_adminship( + ref self: ComponentState, new_super_admin: ContractAddress + ) { + self.assert_only_super_admin(); + self._propose_super_admin(new_super_admin); + } + + /// Returns the time for which handover is valid for pending super_admin. + fn super_admin_ownership_valid_for(self: @ComponentState) -> u64 { + 72 * 3600 + } + } + + #[generate_trait] + pub impl InternalImpl< + TContractState, + +HasComponent, + +Drop + > of InternalTrait { + + fn initializer(ref self: ComponentState, super_admin: ContractAddress) { + self.Super_admin.write(super_admin); + self.Total_signer.write(1); + self.Signers.write(super_admin, true); + } + + fn _renounce_signership( + ref self: ComponentState, _from: ContractAddress, _to: ContractAddress + ) { + self.Signers.write(_from, false); + self.Signers.write(_to, true); + + // self.emit(SignerRenounced { from: _from, to: _to }); + } + fn assert_only_super_admin(self: @ComponentState) { + let super_admin = self.Super_admin.read(); + let caller = get_caller_address(); + assert(!caller.is_zero(), Errors::ZERO_ADDRESS_CALLER); + assert(caller == super_admin, Errors::NOT_OWNER); + } + + fn _accept_super_adminship(ref self: ComponentState) { + let caller = get_caller_address(); + let pending_super_admin = self.Pending_admin.read(); + let super_adminship_expires_at: u64 = self.Handover_expires.read(); + assert(caller == pending_super_admin, Errors::NOT_PENDING_OWNER); + assert(get_block_timestamp() <= super_adminship_expires_at, Errors::HANDOVER_EXPIRED); + // self._transfer_super_adminship(pending_super_admin); + } + + fn _transfer_super_adminship( + ref self: ComponentState, new_super_admin: ContractAddress + ) { + self.Pending_admin.write(Zero::zero()); + self.Handover_expires.write(0); + + let previous_super_admin: ContractAddress = self.Super_admin.read(); + self.Super_admin.write(new_super_admin); + self + .emit( + SuperOwnershipTransferred { + previous_super_admin: previous_super_admin, new_super_admin: new_super_admin + } + ); + } + fn _propose_super_admin( + ref self: ComponentState, new_super_admin: ContractAddress + ) { + let previous_super_admin = self.Super_admin.read(); + self.Pending_admin.write(new_super_admin); + let super_adminship_expires_at = get_block_timestamp() + + 72 * 3600; + self.Handover_expires.write(super_adminship_expires_at); + self + .emit( + SuperOwnershipTransferStarted { + previous_super_admin: previous_super_admin, new_super_admin: new_super_admin + } + ); + } + + } + + + + + + + + +} \ No newline at end of file diff --git a/cairo/src/contracts/HSTK.cairo b/cairo/src/contracts/HSTK.cairo index e69de29..4385605 100644 --- a/cairo/src/contracts/HSTK.cairo +++ b/cairo/src/contracts/HSTK.cairo @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: MIT +use starknet::ContractAddress; + +#[starknet::interface] +pub trait IHashToken{ + + fn permissioned_mint(ref self: TContractState, account: ContractAddress, amount: u256); + fn permissioned_burn(ref self: TContractState, account: ContractAddress, amount: u256); + fn total_supply(self: @TContractState) -> u256; + + fn balance_of(self: @TContractState, account: ContractAddress) -> u256; + + fn allowance( + self: @TContractState, owner: ContractAddress, spender: ContractAddress + ) -> u256; + + fn transfer( + ref self: TContractState, recipient: ContractAddress, amount: u256 + ) -> bool; + + fn transfer_from( + ref self: TContractState, + sender: ContractAddress, + recipient: ContractAddress, + amount: u256 + ) -> bool; + + fn approve( + ref self: TContractState, spender: ContractAddress, amount: u256) -> bool; + + // IERC20Metadata + fn name(self:@TContractState) -> ByteArray; + fn symbol(self:@TContractState) -> ByteArray; + fn decimals(self:@TContractState) -> u8; + + +} +#[starknet::interface] +pub trait IHashTokenCamel{ + + fn permissionedMint(ref self: TContractState, account: ContractAddress, amount: u256); + fn permissionedBurn(ref self: TContractState, account: ContractAddress, amount: u256); + fn totalSupply(self: @TContractState) -> u256; + fn balanceOf(self: @TContractState, account: ContractAddress) -> u256; + fn transferFrom( + ref self: TContractState, + sender: ContractAddress, + recipient: ContractAddress, + amount: u256 + ) -> bool; + +} + +#[starknet::contract] +mod HSTK { + use starknet::{ClassHash, ContractAddress, get_caller_address}; + // use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE}; + use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use super::IHashToken; + use super::IHashTokenCamel; + // use cairo::components::AccessRegistry::AccessRegistryComp::{InternalImpl,AccessRegistry}; + // use cairo::interfaces::IHashToken::{IHashToken, IHashTokenCamel}; + use cairo::components::BlackListed::BlackListedComp; + component!(path: BlackListedComp, storage: blacklisted, event: BlackListedEvent); + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + + // #[abi(embed_v0)] + // impl AccessControlImpl = access_comp::AccessControlImpl; + // impl AccessControlInternalImpl = access_comp::InternalImpl; + + + impl ERC20MixinImpl = ERC20Component::ERC20Mixin; + + impl ERC20InternalImpl = ERC20Component::InternalImpl; + impl BlackListedInternalImpl = BlackListedComp::InternalImpl; + + #[abi(embed_v0)] + impl BlackListedImpl = BlackListedComp::BlackListed; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage, + #[substorage(v0)] + blacklisted: BlackListedComp::Storage, + bridge: ContractAddress, + l1_token:ContractAddress + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event, + #[flat] + SRC5Event: SRC5Component::Event, + #[flat] + BlackListedEvent: BlackListedComp::Event, + + } + + #[constructor] + fn constructor( + ref self: ContractState, + default_admin: ContractAddress, + bridge: ContractAddress, + l1_token: ContractAddress, + multi_sig:ContractAddress + ) { + self.erc20.initializer("HSTK", "HSTK"); + self.blacklisted.initializer(multi_sig); + self.l1_token.write(l1_token); + self.bridge.write(bridge); + } + + #[abi(embed_v0)] + impl HashTokenImpl of IHashToken { + fn permissioned_mint(ref self: ContractState, account: ContractAddress, amount: u256) { + self.assert_only_bridge(); + self.erc20._mint(account, amount); + } + fn permissioned_burn(ref self: ContractState, account: ContractAddress, amount: u256) { + self.assert_only_bridge(); + self.erc20._burn(get_caller_address(), amount); + } + fn total_supply(self:@ContractState) -> u256 { + self.erc20.total_supply() + } + + fn balance_of(self: @ContractState, account: ContractAddress) -> u256{ + self.erc20.balance_of(account) + } + + fn allowance( + self: @ContractState, owner: ContractAddress, spender: ContractAddress + ) -> u256 { + self.erc20.allowance(owner, spender) + } + + fn transfer( + ref self: ContractState, recipient: ContractAddress, amount: u256 + ) -> bool { + + self.blacklisted._not_blacklisted(recipient); + self.blacklisted._not_blacklisted(get_caller_address()); + // should be active + self.erc20.transfer(recipient, amount) + } + + fn transfer_from( + ref self: ContractState, + sender: ContractAddress, + recipient: ContractAddress, + amount: u256 + ) -> bool { + + self.blacklisted._not_blacklisted(recipient); + self.blacklisted._not_blacklisted(recipient); + self.erc20.transfer_from(sender, recipient, amount) + } + + fn approve( + ref self: ContractState, spender: ContractAddress, amount: u256 + ) -> bool { + self.blacklisted._not_blacklisted(spender); + self.blacklisted._not_blacklisted(get_caller_address()); + self.erc20.approve(spender, amount) + } + + // IERC20Metadata + fn name(self: @ContractState) -> ByteArray { + self.erc20.name() + } + + fn symbol(self: @ContractState) -> ByteArray { + self.erc20.symbol() + } + + fn decimals(self: @ContractState) -> u8 { + self.erc20.decimals() + } + + } + + #[abi(embed_v0)] + impl HashTokenCamelImpl of IHashTokenCamel { + fn permissionedMint(ref self: ContractState, account: ContractAddress, amount: u256){ + HashTokenImpl::permissioned_mint(ref self, account, amount) + } + fn permissionedBurn(ref self: ContractState, account: ContractAddress, amount: u256) { + HashTokenImpl::permissioned_burn(ref self, account, amount) + } + + // IERC20CamelOnly + fn totalSupply(self: @ContractState) -> u256 { + HashTokenImpl::total_supply(self) + } + + fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { + HashTokenImpl::balance_of(self, account) + } + + fn transferFrom( + ref self: ContractState, + sender: ContractAddress, + recipient: ContractAddress, + amount: u256 + ) -> bool { + HashTokenImpl::transfer_from(ref self, sender, recipient, amount) + } + } + + + #[generate_trait] + impl HSTKInternalImpl of InternalTrait { + fn assert_only_bridge(self: @ContractState){ + + let caller = get_caller_address(); + let bridge = self.bridge.read(); + assert(caller == bridge,'Only Bridge'); + + } + } +} \ No newline at end of file diff --git a/cairo/src/contracts/Multisig.cairo b/cairo/src/contracts/Multisig.cairo new file mode 100644 index 0000000..e3df531 --- /dev/null +++ b/cairo/src/contracts/Multisig.cairo @@ -0,0 +1,412 @@ + +// use starknet::{ContractAddress,ClassHash}; +// #[derive(Copy, Drop, Serde, starknet::Store)] +// pub enum TransactionState { +// Pending, +// Active, +// Queued, +// Expired, +// Executed +// } + +// pub fn resolve_tx_state(state: TransactionState) -> felt252 { +// match state { +// TransactionState::Pending => 0, +// TransactionState::Active => 1, +// TransactionState::Queued => 2, +// TransactionState::Expired => 3, +// TransactionState::Executed => 4, + +// } +// } + +// #[starknet::interface] +// pub trait IMultiSigL2 { +// fn upgrade(ref self: TContractState, new_class_hash: ClassHash); +// fn create_blacklist_tx(ref self:TContractState, account:ContractAddress)->felt252; +// fn create_removeBlacklisted_tx(ref self:TContractState, account:ContractAddress)->felt252; +// fn create_recover_token_tx(ref self: TContractState,asset:ContractAddress, receipient:ContractAddress)->felt252; +// fn update_pauseState_tx(ref self:TContractState,state:u8)->felt252; +// fn update_transaction_state(ref self:TContractState,tx_id:felt252)->TransactionState; +// fn approve_transaction(ref self: TContractState,tx_id:felt252); +// fn revoke_signatory(ref self: TContractState,tx_id:felt252); +// fn execute_transaction(ref self: TContractState,tx_id:felt252); +// fn is_valid_tx(self:@TContractState,tx_id:felt252)->bool; +// } +// #[starknet::contract] +// pub mod MultiSigL2{ + +// use starknet::{ContractAddress,ClassHash,SyscallResultTrait}; +// use starknet::{get_caller_address,get_block_timestamp}; +// // use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; +// use starknet::storage::{ +// StoragePointerReadAccess, StoragePointerWriteAccess, StoragePathEntry +// }; +// use core::array::ArrayTrait; +// use core::option::OptionTrait; +// use cairo::components::AccessRegistry::AccessRegistryComp; +// use cairo::components::AccessRegistry::AccessRegistryComp::{InternalImpl,AccessRegistyImpl}; +// // use cairo::components::AccessRegistry::AccessRegistryComp::AccessRegistyImpl; +// // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp; +// // use cairo::components::SuperAdmin2Step::SuperAdminTwoStep::SuperAdminTwoStepImpl; +// use openzeppelin::upgrades::{UpgradeableComponent, interface::IUpgradeable}; +// use openzeppelin::introspection::src5::SRC5Component; +// use super::{TransactionState,resolve_tx_state}; +// use core::num::traits::Zero; +// use core::pedersen::PedersenTrait; +// use starknet::account::Call; +// use starknet::syscalls::call_contract_syscall; +// use core::starknet::event::EventEmitter; + +// component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); +// component!(path: SRC5Component, storage: src5, event: SRC5Event); +// component!(path: AccessRegistryComp , storage: access_registry , event: AccessRegistryEvent); + + +// /// Upgradeable +// impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl; +// impl AccessRegistryInternalImpl = AccessRegistryComp::InternalImpl; + +// // Constants +// pub const SIGNER_WINDOW: u64 = 86400; // 24 hours in seconds +// pub const APPROVAL_THRESHOLD: u64 = 60; // 60% of signers must approve + +// // Function selectors as constants +// pub const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); +// pub const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); +// pub const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); +// pub const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); + +// #[derive(Drop, Serde,starknet::store)] +// pub struct Transaction { +// proposer: ContractAddress, +// selector: felt252, +// params : Array, +// proposed_at: u64, +// first_sign_at: u64, +// approvals: u64 +// } + +// #[storage] +// struct Storage { + +// #[substorage(v0)] +// upgradeable: UpgradeableComponent::Storage, +// #[substorage(v0)] +// src5: SRC5Component::Storage, +// #[substorage(v0)] +// access_registry: AccessRegistryComp::Storage, +// token_contract: ContractAddress, +// transactions: LegacyMap::, +// has_approved: LegacyMap::<(felt252, ContractAddress), bool>, +// transaction_exists: LegacyMap::, +// signer_functions: LegacyMap::, +// transaction_state: LegacyMap::, +// } + +// #[event] +// #[derive(Drop,starknet::Event)] +// enum Event{ +// TransactionProposed: TransactionProposed, +// TransactionApproved: TransactionApproved, +// SignatoryRevoked: SignatoryRevoked, +// TransactionExecuted: TransactionExecuted, +// TransactionExpired: TransactionExpired, +// TransactionStateChanged: TransactionStateChanged, +// #[flat] +// UpgradeableEvent: UpgradeableComponent::Event, +// #[flat] +// SRC5Event: SRC5Component::Event, +// #[flat] +// AccessRegistryEvent: AccessRegistryComp::Event, +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionProposed { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub proposer:ContractAddress, +// #[key] +// pub proposed_at: u64, +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionApproved { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub signer: ContractAddress, +// } + +// #[derive(Drop,starknet::Event)] +// pub struct SignatoryRevoked { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub revoker: ContractAddress, +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionExecuted { +// #[key] +// pub tx_id: felt252 +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionExpired { +// #[key] +// pub tx_id: felt252 +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionStateChanged { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub new_state: TransactionState, +// } + +// pub mod Error{ +// pub const ZERO_ADDRESS:felt252 = 'CAlldata consist Zero Address'; +// } + +// #[abi(embed_v0)] +// impl AccessRegistyImpl = +// AccessRegistryComp::Access_Registry; + +// #[constructor] +// fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress){ +// assert(!token_l2.is_zero() && !super_admin.is_zero(),Error::ZERO_ADDRESS); +// self.access_registry.initializer(super_admin); +// self.token_contract.write(token_l2); +// } + +// #[abi(embed_v0)] +// impl MultiSigL2Impl of super::IMultiSigL2{ + +// fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { +// self.access_registry.assert_only_super_admin(); +// self.upgradeable.upgrade(new_class_hash); +// } + +// fn create_blacklist_tx(ref self:ContractState, account:ContractAddress)->felt252 { + +// assert(!account.is_zero(),Error::ZERO_ADDRESS); +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let mut calldata:Array = array![]; +// Serde::serialize(@account, ref calldata); +// self._route_standarad_transaction(BLACKLIST_ACCOUNT_SELECTOR,calldata) +// } +// fn create_removeBlacklisted_tx(ref self:ContractState, account:ContractAddress)->felt252{ + +// assert(!account.is_zero(),Error::ZERO_ADDRESS); +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let mut calldata:Array = array![]; +// Serde::serialize(@account, ref calldata); +// self._route_standarad_transaction(REMOVE_BLACKLIST_ACCOUNT_SELECTOR,calldata) + +// } +// fn create_recover_token_tx(ref self: ContractState,asset:ContractAddress, receipient:ContractAddress)->felt252{ + +// assert(!asset.is_zero() &&!receipient.is_zero() ,Error::ZERO_ADDRESS); +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let mut calldata:Array = array![]; +// Serde::serialize(@asset, ref calldata); +// Serde::serialize(@receipient, ref calldata); +// self._route_standarad_transaction(RECOVER_TOKENS_SELECTOR,calldata) + +// } +// fn update_pauseState_tx(ref self:ContractState,state:u8)->felt252{ + +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let mut calldata:Array = array![]; +// Serde::serialize(@state, ref calldata); +// self._route_standarad_transaction(PAUSE_STATE_SELECTOR,calldata) + +// } +// fn update_transaction_state(ref self:ContractState,tx_id:felt252)->TransactionState{ +// self._assert_transaction_exists(tx_id); + +// let mut transaction= self.transactions.read(tx_id); +// let transaction_s = self.transaction_state.read(tx_id); + +// if (transaction_s == TransactionState::Expired){ +// transaction_s +// } +// if(transaction_s == TransactionState::Executed){ +// transaction_s +// } +// let current_time = get_block_timestamp(); + +// let isExpired:bool = current_time > transaction.first_sign_at + SIGNER_WINDOW; + +// let mut new_state:TransactionState = transaction_s; +// let total_signers:u64 = self.access_registry.total_signer(); + +// if(isExpired){ +// if((transaction.approvals * 100) / total_signers >= APPROVAL_THRESHOLD){ +// new_state = TransactionState::Queued; +// }else{ +// //emit an Insufficient Approval Event +// self.emit( +// TransactionExpired{ +// tx_id: tx_id +// } +// ); +// new_state = TransactionState::Expired; +// } +// }else if(transaction.first_sign_at!=0){ +// new_state = TransactionState::Active; +// } + +// if (new_state != transaction_s) { +// self.transaction_state.write(tx_id,new_state); +// // self.(emit{TransactionStateChanged(txId, transaction.state)}); +// } + +// new_state + +// } +// fn is_valid_tx(self:@ContractState,tx_id:felt252)->bool{ +// true +// } + +// fn approve_transaction(ref self: ContractState, tx_id: felt252) { + +// self._assert_transaction_exists(tx_id); +// let caller = get_caller_address(); +// let current_timestamp =get_block_timestamp(); +// assert(self.access_registry.is_signer(caller), 'Not a signer'); +// assert(!self.has_approved.read((tx_id, caller)), 'Already approved'); + +// let mut transaction = self.transactions.read(tx_id); +// let current_state = self.update_transaction_state(tx_id); + +// assert( +// current_state == TransactionState::Pending || +// current_state == TransactionState::Active, +// 'Invalid state' +// ); + +// if transaction.approvals == 0 { +// transaction.first_sign_at = current_timestamp; +// } + +// transaction.approvals += 1 ; +// self.has_approved.write((tx_id, caller), true); +// self.transactions.write(tx_id, transaction); + +// self.emit(TransactionApproved { tx_id, signer: caller }); +// } +// fn revoke_signatory(ref self: ContractState,tx_id:felt252){ + +// self._assert_transaction_exists(tx_id); +// let caller = get_caller_address(); +// let current_timestamp =get_block_timestamp(); +// assert(self.access_registry.is_signer(caller), 'Not a signer'); +// assert(self.has_approved.read((tx_id, caller)), 'Not approved'); + +// let mut transaction = self.transactions.read(tx_id); +// let current_state = self.update_transaction_state(tx_id); + +// assert( +// current_state == TransactionState::Active, +// 'Invalid state for Revoke Signature' +// ); +// transaction.approvals -= 1; +// self.has_approved.write((tx_id, caller), false); +// self.transactions.write(tx_id, transaction); +// self.emit(SignatoryRevoked { tx_id: tx_id, revoker: caller }); + + +// } +// fn execute_transaction(ref self: ContractState, tx_id: felt252) { +// self._assert_transaction_exists(tx_id); +// let mut transaction = self.transactions.read(tx_id); +// let current_state = self.update_transaction_state(tx_id); + +// assert(current_state == TransactionState::Queued, 'Invalid state'); +// self.transaction_state.write(tx_id,TransactionState::Executed); +// // self.transactions.write(tx_id, transaction); +// let function_selector = transaction.selector.clone(); +// let params = transaction.params.clone(); + +// self._call(function_selector, params); +// self.emit(TransactionExecuted { tx_id }); +// } + +// } +// #[generate_trait] +// impl MultiSigInternalImpl of InternalTrait { +// fn _route_standarad_transaction(self: @ContractState, function_selector: felt252 , calldata:Array)->felt252{ +// let caller: ContractAddress = get_caller_address(); +// let super_admin:ContractAddress = self.access_registry.super_admin(); +// if caller==super_admin { +// self._call(function_selector,calldata) +// }else{ +// self._create_transaction(function_selector,calldata) +// } + +// } + +// fn _assert_transaction_exists(self: @ContractState, tx_id: felt252) { +// assert(self.transaction_exists.read(tx_id), 'Transaction not found'); +// } + +// fn _create_transaction( +// ref self: ContractState, +// selector: felt252, +// params: Array +// ) -> felt252 { +// let caller = get_caller_address(); +// let is_signer = self.access_registry.is_signer(caller); +// let timestamp = get_block_timestamp(); +// let is_valid_function:bool = self.signer_functions.read(selector); + +// assert(is_valid_function && is_signer , 'Unauthorized'); + +// // let tx_id = PedersenTrait::new(0).update_with(params).update_with(timestamp).update_with(selector).finalize(); +// let tx_id = get_block_timestamp().into(); + + +// //For multiple transaction with same params andd calldata in a single Block. +// assert(!self.transaction_exists.read(tx_id), 'Transaction exists'); + +// self.transaction_exists.write(tx_id, true); +// let transaction:Transaction = Transaction { +// proposer: caller, +// selector, +// params, +// proposed_at: timestamp, +// first_sign_at: 0, +// approvals: 0 +// }; + +// self.transactions.write(tx_id, transaction); +// self.transaction_state.write(tx_id,TransactionState::Pending); +// self.emit(TransactionProposed { +// tx_id, +// proposer: caller, +// proposed_at: get_block_timestamp() +// }); + +// tx_id +// } + +// fn _call(self:@ContractState, function_selector:felt252, calldata:Array)->felt252{ +// get_block_timestamp().into() + +// } + + +// // const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); +// // const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); +// // const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); +// // const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); + + +// } + +// } + diff --git a/cairo/src/contracts/MultisigL2.cairo b/cairo/src/contracts/MultisigL2.cairo index c831221..77a51fb 100644 --- a/cairo/src/contracts/MultisigL2.cairo +++ b/cairo/src/contracts/MultisigL2.cairo @@ -1,405 +1,409 @@ -use starknet::{ContractAddress,ClassHash}; -#[derive(Copy, Drop, Serde, starknet::Store)] -pub enum TransactionState { - Pending, - Active, - Queued, - Expired, - Executed, -} - -pub fn resolve_tx_state(state: TransactionState) -> felt252 { - match state { - TransactionState::Pending => 0, - TransactionState::Active => 1, - TransactionState::Queued => 2, - TransactionState::Expired => 3, - TransactionState::Executed => 4, +// use starknet::{ContractAddress,ClassHash}; +// #[derive(Copy, Drop, Serde, starknet::Store)] +// pub enum TransactionState { +// Pending, +// Active, +// Queued, +// Expired, +// Executed +// } + +// pub fn resolve_tx_state(state: TransactionState) -> felt252 { +// match state { +// TransactionState::Pending => 0, +// TransactionState::Active => 1, +// TransactionState::Queued => 2, +// TransactionState::Expired => 3, +// TransactionState::Executed => 4, - } -} - -#[starknet::interface] -pub trait IMultiSigL2 { - fn upgrade(ref self: TContractState, new_class_hash: ClassHash); - fn create_blacklist_tx(ref self:TContractState, account:ContractAddress)->felt252; - fn create_removeBlacklisted_tx(ref self:TContractState, account:ContractAddress)->felt252; - fn create_recover_token_tx(ref self: TContractState,asset:ContractAddress, receipient:ContractAddress)->felt252; - fn update_pauseState_tx(ref self:TContractState,state:u8)->felt252; - fn update_transaction_state(ref self:TContractState,tx_id:felt252)->TransactionState; - fn approve_transaction(ref self: TContractState,tx_id:felt252); - fn revoke_signatory(ref self: TContractState,tx_id:felt252); - fn execute_transaction(ref self: TContractState,tx_id:felt252); - fn is_valid_tx(self:@TContractState,tx_id:felt252)->bool; -} -#[starknet::contract] -mod MultiSigL2{ - - use starknet::{ContractAddress,ClassHash,SyscallResultTrait}; - use starknet::{get_caller_address,get_block_timestamp}; - // use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; - // use starknet::storage::{ - // StoragePointerReadAccess, StoragePointerWriteAccess, StoragePathEntry, Map - // }; - use core::array::ArrayTrait; - use core::option::OptionTrait; - use cairo::components::AccessRegistry::AccessRegistryComp; - // use cairo::components::AccessRegistry::AccessRegistryComp::AccessRegistyImpl; - // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp; - // use cairo::components::SuperAdmin2Step::SuperAdminTwoStep::SuperAdminTwoStepImpl; - use openzeppelin::upgrades::{UpgradeableComponent, interface::IUpgradeable}; - use openzeppelin::introspection::src5::SRC5Component; - use super::{TransactionState,resolve_tx_state}; - use core::num::traits::Zero; - use core::pedersen::PedersenTrait; - use starknet::account::Call; - use starknet::syscalls::call_contract_syscall; - use core::starknet::event::EventEmitter; - - - component!(path: AccessRegistryComp , storage: accessRegistry , event: AccessRegistryEvents); - component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - - /// Upgradeable - impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl; - impl AccessRegistryImpl = AccessRegistryComp::AccessRegisty; - impl AccessRegistryInternalImpl = AccessRegistryComp::InternalImpl; - - // Constants - pub const SIGNER_WINDOW: u64 = 86400; // 24 hours in seconds - pub const APPROVAL_THRESHOLD: u64 = 60; // 60% of signers must approve +// } +// } + +// #[starknet::interface] +// pub trait IMultiSigL2 { +// fn upgrade(ref self: TContractState, new_class_hash: ClassHash); +// fn create_blacklist_tx(ref self:TContractState, account:ContractAddress)->felt252; +// fn create_removeBlacklisted_tx(ref self:TContractState, account:ContractAddress)->felt252; +// fn create_recover_token_tx(ref self: TContractState,asset:ContractAddress, receipient:ContractAddress)->felt252; +// fn update_pauseState_tx(ref self:TContractState,state:u8)->felt252; +// fn update_transaction_state(ref self:TContractState,tx_id:felt252)->TransactionState; +// fn approve_transaction(ref self: TContractState,tx_id:felt252); +// fn revoke_signatory(ref self: TContractState,tx_id:felt252); +// fn execute_transaction(ref self: TContractState,tx_id:felt252); +// fn is_valid_tx(self:@TContractState,tx_id:felt252)->bool; +// } +// #[starknet::contract] +// pub mod MultiSigL2{ + +// use starknet::{ContractAddress,ClassHash,SyscallResultTrait}; +// use starknet::{get_caller_address,get_block_timestamp}; +// // use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; +// use starknet::storage::{ +// StoragePointerReadAccess, StoragePointerWriteAccess, StoragePathEntry +// }; +// use core::array::ArrayTrait; +// use core::option::OptionTrait; +// use cairo::components::AccessRegistry::AccessRegistryComp; +// use cairo::components::AccessRegistry::AccessRegistryComp::{InternalImpl,AccessRegistyImpl}; +// // use cairo::components::AccessRegistry::AccessRegistryComp::AccessRegistyImpl; +// // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp; +// // use cairo::components::SuperAdmin2Step::SuperAdminTwoStep::SuperAdminTwoStepImpl; +// use openzeppelin::upgrades::{UpgradeableComponent, interface::IUpgradeable}; +// use openzeppelin::introspection::src5::SRC5Component; +// use super::{TransactionState,resolve_tx_state}; +// use core::num::traits::Zero; +// use core::pedersen::PedersenTrait; +// use starknet::account::Call; +// use starknet::syscalls::call_contract_syscall; +// use core::starknet::event::EventEmitter; + +// component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); +// component!(path: SRC5Component, storage: src5, event: SRC5Event); +// component!(path: AccessRegistryComp , storage: access_registry , event: AccessRegistryEvent); + + +// #[abi(embed_v0)] +// impl AccessRegistyImpl = AccessRegistryComp::Access_Registry; +// /// Upgradeable +// impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl; +// impl AccessRegistryInternalImpl = AccessRegistryComp::InternalImpl; + +// // Constants +// pub const SIGNER_WINDOW: u64 = 86400; // 24 hours in seconds +// pub const APPROVAL_THRESHOLD: u64 = 60; // 60% of signers must approve - // Function selectors as constants - pub const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); - pub const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); - pub const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); - pub const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); - - #[derive(Drop, Serde, starknet::Store)] - pub struct Transaction { - proposer: ContractAddress, - selector: felt252, - params : Array, - proposed_at: u64, - first_sign_at: u64, - approvals: u64, - state: TransactionState - } - - #[storage] - pub struct Storage { - token_contract: ContractAddress, - transactions: LegacyMap::, - has_approved: LegacyMap::<(felt252, ContractAddress), bool>, - transaction_exists: LegacyMap::, - signer_functions: LegacyMap::, - #[substorage(v0)] - accessRegistry: AccessRegistryComp::Storage, - #[substorage(v0)] - upgradeable: UpgradeableComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop,starknet::Event)] - pub enum Event{ - TransactionProposed: TransactionProposed, - TransactionApproved: TransactionApproved, - SignatoryRevoked: SignatoryRevoked, - TransactionExecuted: TransactionExecuted, - TransactionExpired: TransactionExpired, - TransactionStateChanged: TransactionStateChanged, - #[flat] - AccessRegistryEvents: AccessRegistryComp::Event, - #[flat] - UpgradeableEvent: UpgradeableComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[derive(Drop,starknet::Event)] - pub struct TransactionProposed { - #[key] - pub tx_id: felt252, - #[key] - pub proposer:ContractAddress, - #[key] - pub proposed_at: u64, - } - - #[derive(Drop,starknet::Event)] - pub struct TransactionApproved { - #[key] - pub tx_id: felt252, - #[key] - pub signer: ContractAddress, - } - - #[derive(Drop,starknet::Event)] - pub struct SignatoryRevoked { - #[key] - pub tx_id: felt252, - #[key] - pub revoker: ContractAddress, - } - - #[derive(Drop,starknet::Event)] - pub struct TransactionExecuted { - #[key] - pub tx_id: felt252 - } - - #[derive(Drop,starknet::Event)] - pub struct TransactionExpired { - #[key] - pub tx_id: felt252 - } - - #[derive(Drop,starknet::Event)] - pub struct TransactionStateChanged { - #[key] - pub tx_id: felt252, - #[key] - pub new_state: TransactionState, - } - - pub mod Error{ - pub const ZERO_ADDRESS:felt252 = 'CAlldata consist Zero Address'; - } - - #[abi(embed_v0)] - impl AccessRegistryImpl = - AccessRegistryComp::AccessRegisty; - - #[constructor] - fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress){ - assert(!token_l2.is_zero() && !super_admin.is_zero(),Error::ZERO_ADDRESS); - self.accessRegistry.initializer(super_admin); - self.token_contract.write(token_l2); - } - - #[abi(embed_v0)] - impl MultiSigL2Impl of super::IMultiSigL2{ - - fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { - self.accessRegistry.assert_only_super_admin(); - self.upgradeable.upgrade(new_class_hash); - } - - fn create_blacklist_tx(ref self:ContractState, account:ContractAddress)->felt252 { - - assert(!account.is_zero(),Error::ZERO_ADDRESS); - assert(!self.accessRegistry.is_signer(get_caller_address()),'Not Signer'); - let mut calldata:Array = array![]; - Serde::serialize(@account, ref calldata); - self._route_standarad_transaction(BLACKLIST_ACCOUNT_SELECTOR,calldata) - } - fn create_removeBlacklisted_tx(ref self:ContractState, account:ContractAddress)->felt252{ - - assert(!account.is_zero(),Error::ZERO_ADDRESS); - assert(!self.accessRegistry.is_signer(get_caller_address()),'Not Signer'); - let mut calldata:Array = array![]; - Serde::serialize(@account, ref calldata); - self._route_standarad_transaction(REMOVE_BLACKLIST_ACCOUNT_SELECTOR,calldata) - - } - fn create_recover_token_tx(ref self: ContractState,asset:ContractAddress, receipient:ContractAddress)->felt252{ - - assert(!asset.is_zero() &&!receipient.is_zero() ,Error::ZERO_ADDRESS); - assert(!self.accessRegistry.is_signer(get_caller_address()),'Not Signer'); - let mut calldata:Array = array![]; - Serde::serialize(@asset, ref calldata); - Serde::serialize(@receipient, ref calldata); - self._route_standarad_transaction(RECOVER_TOKENS_SELECTOR,calldata) - - } - fn update_pauseState_tx(ref self:ContractState,state:u8)->felt252{ - - assert(!self.accessRegistry.is_signer(get_caller_address()),'Not Signer'); - let mut calldata:Array = array![]; - Serde::serialize(@state, ref calldata); - self._route_standarad_transaction(PAUSE_STATE_SELECTOR,calldata) - - } - fn update_transaction_state(ref self:ContractState,tx_id:felt252)->TransactionState{ - self._assert_transaction_exists(tx_id); - let mut transaction:Transaction = self.transactions.read(tx_id); - - if resolve_tx_state(transaction.state) == resolve_tx_state(TransactionState::Expired) || resolve_tx_state(transaction.state) == resolve_tx_state(TransactionState::Executed){ - transaction.state - } - let current_time = get_block_timestamp(); +// // Function selectors as constants +// pub const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); +// pub const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); +// pub const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); +// pub const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); + +// #[derive(Drop, Serde,starknet::Store)] +// pub struct Transaction { +// proposer: ContractAddress, +// selector: felt252, +// params : Array, +// proposed_at: u64, +// first_sign_at: u64, +// approvals: u64, +// state: TransactionState +// } + +// #[storage] +// struct Storage { + +// #[substorage(v0)] +// upgradeable: UpgradeableComponent::Storage, +// #[substorage(v0)] +// src5: SRC5Component::Storage, +// #[substorage(v0)] +// access_registry: AccessRegistryComp::Storage, +// token_contract: ContractAddress, +// transactions: LegacyMap::, +// has_approved: LegacyMap::<(felt252, ContractAddress), bool>, +// transaction_exists: LegacyMap::, +// signer_functions: LegacyMap:: +// } + +// #[event] +// #[derive(Drop,starknet::Event)] +// enum Event{ +// TransactionProposed: TransactionProposed, +// TransactionApproved: TransactionApproved, +// SignatoryRevoked: SignatoryRevoked, +// TransactionExecuted: TransactionExecuted, +// TransactionExpired: TransactionExpired, +// TransactionStateChanged: TransactionStateChanged, +// #[flat] +// UpgradeableEvent: UpgradeableComponent::Event, +// #[flat] +// SRC5Event: SRC5Component::Event, +// #[flat] +// AccessRegistryEvent: AccessRegistryComp::Event, +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionProposed { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub proposer:ContractAddress, +// #[key] +// pub proposed_at: u64, +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionApproved { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub signer: ContractAddress, +// } + +// #[derive(Drop,starknet::Event)] +// pub struct SignatoryRevoked { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub revoker: ContractAddress, +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionExecuted { +// #[key] +// pub tx_id: felt252 +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionExpired { +// #[key] +// pub tx_id: felt252 +// } + +// #[derive(Drop,starknet::Event)] +// pub struct TransactionStateChanged { +// #[key] +// pub tx_id: felt252, +// #[key] +// pub new_state: TransactionState, +// } + +// pub mod Error{ +// pub const ZERO_ADDRESS:felt252 = 'CAlldata consist Zero Address'; +// } + + +// #[constructor] +// fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress){ +// assert(!token_l2.is_zero() && !super_admin.is_zero(),Error::ZERO_ADDRESS); +// self.access_registry.initializer(super_admin); +// self.token_contract.write(token_l2); +// } + +// #[abi(embed_v0)] +// impl MultiSigL2Impl of super::IMultiSigL2{ + +// fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { +// self.access_registry.assert_only_super_admin(); +// self.upgradeable.upgrade(new_class_hash); +// } + +// fn create_blacklist_tx(ref self:ContractState, account:ContractAddress)->felt252 { + +// assert(!account.is_zero(),Error::ZERO_ADDRESS); +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let calldata:Array = array![account.into()]; +// // Serde::serialize(@account, ref calldata); +// self._route_standarad_transaction(BLACKLIST_ACCOUNT_SELECTOR,calldata) +// } +// fn create_removeBlacklisted_tx(ref self:ContractState, account:ContractAddress)->felt252{ + +// assert(!account.is_zero(),Error::ZERO_ADDRESS); +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let mut calldata:Array = array![account.into()]; +// // Serde::serialize(@account, ref calldata); +// self._route_standarad_transaction(REMOVE_BLACKLIST_ACCOUNT_SELECTOR,calldata) + +// } +// fn create_recover_token_tx(ref self: ContractState,asset:ContractAddress, receipient:ContractAddress)->felt252{ + +// assert(!asset.is_zero() &&!receipient.is_zero() ,Error::ZERO_ADDRESS); +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let mut calldata:Array = array![asset.into(),receipient.into()]; +// // Serde::serialize(@asset, ref calldata); +// // Serde::serialize(@receipient, ref calldata); +// self._route_standarad_transaction(RECOVER_TOKENS_SELECTOR,calldata) + +// } +// fn update_pauseState_tx(ref self:ContractState,state:felt252)->felt252{ + +// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); +// let mut calldata:Array = array![state.into()]; +// // Serde::serialize(@state, ref calldata); +// self._route_standarad_transaction(PAUSE_STATE_SELECTOR,calldata) + +// } +// fn update_transaction_state(ref self:ContractState,tx_id:felt252)->TransactionState{ +// self._assert_transaction_exists(tx_id); +// let mut transaction= self.transactions.read(tx_id); + +// if (resolve_tx_state(transaction.state.read()) == resolve_tx_state(TransactionState::Expired)){ +// transaction.state +// } +// if(resolve_tx_state(transaction.state.read()) == resolve_tx_state(TransactionState::Executed)){ +// transaction.state.read() +// } +// let current_time = get_block_timestamp(); - let isExpired:bool = current_time > transaction.first_sign_at + SIGNER_WINDOW; - - let mut new_state:TransactionState = transaction.state; - let total_signers:u64 = self.accessRegistry.total_signers(); - - if(isExpired){ - if((transaction.approvals * 100) / total_signers >= APPROVAL_THRESHOLD){ - new_state = TransactionState::Queued; - }else{ - //emit an Insufficient Approval Event - self.emit( - TransactionExpired{ - tx_id: tx_id - } - ); - new_state = TransactionState::Expired; - } - }else if(transaction.first_sign_at!=0){ - new_state = TransactionState::Active; - } - - if (resolve_tx_state(new_state) != resolve_tx_state(transaction.state)) { - transaction.state = new_state; - // self.(emit{TransactionStateChanged(txId, transaction.state)}); - } +// let isExpired:bool = current_time > transaction.first_sign_at.read() + SIGNER_WINDOW; + +// let mut new_state:TransactionState = transaction.state.read(); +// let total_signers:u64 = self.access_registry.total_signer(); + +// if(isExpired){ +// if((transaction.approvals * 100) / total_signers >= APPROVAL_THRESHOLD){ +// new_state = TransactionState::Queued; +// }else{ +// //emit an Insufficient Approval Event +// self.emit( +// TransactionExpired{ +// tx_id: tx_id +// } +// ); +// new_state = TransactionState::Expired; +// } +// }else if(transaction.first_sign_at!=0){ +// new_state = TransactionState::Active; +// } + +// if (resolve_tx_state(new_state) != resolve_tx_state(transaction.state)) { +// transaction.state = new_state; +// // self.(emit{TransactionStateChanged(txId, transaction.state)}); +// } - new_state +// new_state - } - fn is_valid_tx(self:@ContractState,tx_id:felt252)->bool{ - true - } - - fn approve_transaction(ref self: ContractState, tx_id: felt252) { - - self._assert_transaction_exists(tx_id); - let caller = get_caller_address(); - let current_timestamp =get_block_timestamp(); - assert(self.accessRegistry.is_signer(caller), 'Not a signer'); - assert(!self.has_approved.read((tx_id, caller)), 'Already approved'); +// } +// fn is_valid_tx(self:@ContractState,tx_id:felt252)->bool{ +// true +// } + +// fn approve_transaction(ref self: ContractState, tx_id: felt252) { + +// self._assert_transaction_exists(tx_id); +// let caller = get_caller_address(); +// let current_timestamp =get_block_timestamp(); +// assert(self.access_registry.is_signer(caller), 'Not a signer'); +// assert(!self.has_approved.read((tx_id, caller)), 'Already approved'); - let mut transaction = self.transactions.read(tx_id); - let current_state = self.update_transaction_state(tx_id); +// let mut transaction = self.transactions.read(tx_id); +// let current_state = self.update_transaction_state(tx_id); - assert( - resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Pending) || - resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Active), - 'Invalid state' - ); +// assert( +// resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Pending) || +// resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Active), +// 'Invalid state' +// ); - if transaction.approvals == 0 { - transaction.first_sign_at = current_timestamp; - } +// if transaction.approvals == 0 { +// transaction.first_sign_at = current_timestamp; +// } - transaction.approvals += 1; - self.has_approved.write((tx_id, caller), true); - self.transactions.write(tx_id, transaction); +// transaction.approvals.write(transaction.approvals.read()+1); +// self.has_approved.write((tx_id, caller), true); +// self.transactions.write(tx_id, transaction); - self.emit(TransactionApproved { tx_id, signer: caller }); - } - fn revoke_signatory(ref self: ContractState,tx_id:felt252){ - - self._assert_transaction_exists(tx_id); - let caller = get_caller_address(); - let current_timestamp =get_block_timestamp(); - assert(self.accessRegistry.is_signer(caller), 'Not a signer'); - assert(self.has_approved.read((tx_id, caller)), 'Not approved'); +// self.emit(TransactionApproved { tx_id, signer: caller }); +// } +// fn revoke_signatory(ref self: ContractState,tx_id:felt252){ + +// self._assert_transaction_exists(tx_id); +// let caller = get_caller_address(); +// let current_timestamp =get_block_timestamp(); +// assert(self.access_registry.is_signer(caller), 'Not a signer'); +// assert(self.has_approved.read((tx_id, caller)), 'Not approved'); - let mut transaction = self.transactions.read(tx_id); - let current_state:TransactionState = self.update_transaction_state(tx_id); +// let mut transaction = self.transactions.read(tx_id); +// let current_state = self.update_transaction_state(tx_id); - assert( - resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Active), - 'Invalid state for Revoke Signature' - ); - transaction.approvals -= 1; - self.has_approved.write((tx_id, caller), false); - self.transactions.write(tx_id, transaction); - self.emit(SignatoryRevoked { tx_id: tx_id, revoker: caller }); - - - } - fn execute_transaction(ref self: ContractState, tx_id: felt252) { - self._assert_transaction_exists(tx_id); - let mut transaction = self.transactions.read(tx_id); - let current_state = self.update_transaction_state(tx_id); - - assert(resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Queued), 'Invalid state'); - transaction.state = TransactionState::Executed; - self.transactions.write(tx_id, transaction); - - self._call(transaction.selector, transaction.params); - self.emit(TransactionExecuted { tx_id }); - } - - } - #[generate_trait] - impl InternalImpl of InternalTrait { - fn _route_standarad_transaction(ref self: ContractState, function_selector: felt252 , calldata:Array)->felt252{ - let caller: ContractAddress = get_caller_address(); - let super_admin:ContractAddress = self.accessRegistry.super_admin(); - if caller==super_admin { - self._call(function_selector,calldata) - }else{ - self._create_transaction(function_selector,calldata) - } - - } - - fn _assert_transaction_exists(ref self: ContractState, tx_id: felt252) { - assert(self.transaction_exists.read(tx_id), 'Transaction not found'); - } - - fn _create_transaction( - ref self: ContractState, - selector: felt252, - params: Array - ) -> felt252 { - let caller = get_caller_address(); - let is_signer = self.accessRegistry.is_signer(caller); - let timestamp = get_block_timestamp(); - let is_valid_function:bool = self.signer_functions.read(selector); +// assert( +// resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Active), +// 'Invalid state for Revoke Signature' +// ); +// transaction.approvals.write(transaction.approvals.read()-1); +// self.has_approved.write((tx_id, caller), false); +// self.transactions.write(tx_id, transaction); +// self.emit(SignatoryRevoked { tx_id: tx_id, revoker: caller }); + + +// } +// fn execute_transaction(ref self: ContractState, tx_id: felt252) { +// self._assert_transaction_exists(tx_id); +// let mut transaction = self.transactions.read(tx_id); +// let current_state = self.update_transaction_state(tx_id); + +// assert(resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Queued), 'Invalid state'); +// transaction.state.read() = TransactionState::Executed; +// // self.transactions.write(tx_id, transaction); +// let function_selector = transaction.selector.read(); +// let params = transaction.params.read(); + +// self._call(function_selector, params); +// self.emit(TransactionExecuted { tx_id }); +// } + +// } +// #[generate_trait] +// impl MultiSigInternalImpl of InternalTrait { +// fn _route_standarad_transaction(self: @ContractState, function_selector: felt252 , calldata:Array)->felt252{ +// let caller: ContractAddress = get_caller_address(); +// let super_admin:ContractAddress = self.access_registry.super_admin(); +// if caller==super_admin { +// self._call(function_selector,calldata) +// }else{ +// self._create_transaction(function_selector,calldata) +// } + +// } + +// fn _assert_transaction_exists(self: @ContractState, tx_id: felt252) { +// assert(self.transaction_exists.read(tx_id), 'Transaction not found'); +// } + +// fn _create_transaction( +// ref self: ContractState, +// selector: felt252, +// params: Array +// ) -> felt252 { +// let caller = get_caller_address(); +// let is_signer = self.access_registry.is_signer(caller); +// let timestamp = get_block_timestamp(); +// let is_valid_function:bool = self.signer_functions.read(selector); - assert(is_valid_function && is_signer , 'Unauthorized'); +// assert(is_valid_function && is_signer , 'Unauthorized'); - // let tx_id = PedersenTrait::new(0).update_with(params).update_with(timestamp).update_with(selector).finalize(); - let tx_id = get_block_timestamp().into(); +// // let tx_id = PedersenTrait::new(0).update_with(params).update_with(timestamp).update_with(selector).finalize(); +// let tx_id = get_block_timestamp().into(); - //For multiple transaction with same params andd calldata in a single Block. - assert(!self.transaction_exists.read(tx_id), 'Transaction exists'); +// //For multiple transaction with same params andd calldata in a single Block. +// assert(!self.transaction_exists.read(tx_id), 'Transaction exists'); - self.transaction_exists.write(tx_id, true); - let transaction:Transaction = Transaction { - proposer: caller, - selector, - params, - proposed_at: timestamp, - first_sign_at: 0, - approvals: 0, - state: TransactionState::Pending - }; +// self.transaction_exists.write(tx_id, true); +// let transaction:Transaction = Transaction { +// proposer: caller, +// selector, +// params, +// proposed_at: timestamp, +// first_sign_at: 0, +// approvals: 0, +// state: TransactionState::Pending +// }; - self.transactions.write(tx_id, transaction); - self.emit(TransactionProposed { - tx_id, - proposer: caller, - proposed_at: get_block_timestamp() - }); +// self.transactions.write(tx_id, transaction); +// self.emit(TransactionProposed { +// tx_id, +// proposer: caller, +// proposed_at: get_block_timestamp() +// }); - tx_id - } +// tx_id +// } - fn _call(self:@ContractState, function_selector:felt252, calldata:Array)->felt252{ - get_block_timestamp().into() +// fn _call(self:@ContractState, function_selector:felt252, calldata:Array)->felt252{ +// get_block_timestamp().into() - } +// } - // const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); - // const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); - // const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); - // const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); +// // const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); +// // const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); +// // const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); +// // const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); - } +// } -} +// } diff --git a/cairo/src/interfaces/IaccessRegistry.cairo b/cairo/src/interfaces/IaccessRegistry.cairo index 826c610..415d0f4 100644 --- a/cairo/src/interfaces/IaccessRegistry.cairo +++ b/cairo/src/interfaces/IaccessRegistry.cairo @@ -1,13 +1,17 @@ use starknet::ContractAddress; + +pub const IACCESSCONTROL_ID: felt252 = + 0x23700be02858dbe2ac4dc9c9f66d0b6b0ed81ec7f970ca6844500a56ff61751; + #[starknet::interface] -pub trait IAccessRegistryComponent { +pub trait IAccessRegistry { + fn is_signer(self: @TContractState, account: ContractAddress) -> bool; + fn get_total_signer(self:@TContractState)->u64; fn add_signer(ref self: TContractState, new_signer: ContractAddress); fn remove_signer(ref self: TContractState, existing_owner: ContractAddress); fn renounce_signership(ref self: TContractState, signer: ContractAddress); - fn is_signer(self: @TContractState, account: ContractAddress) -> bool; fn accept_super_adminship(ref self: TContractState); - fn total_signer(self:@TContractState)->u64; - fn super_admin(self: @TContractState) -> ContractAddress; + fn get_super_admin(self: @TContractState) -> ContractAddress; fn pending_super_admin(self: @TContractState) -> ContractAddress; fn transfer_super_adminship(ref self: TContractState, new_super_admin: ContractAddress); fn super_admin_ownership_valid_for(self: @TContractState) -> u64; diff --git a/cairo/src/interfaces/Ipausable.cairo b/cairo/src/interfaces/Ipausable.cairo index 4bb5be7..3ff3297 100644 --- a/cairo/src/interfaces/Ipausable.cairo +++ b/cairo/src/interfaces/Ipausable.cairo @@ -22,3 +22,4 @@ fn get_state_felt(state: PauseState) -> felt252 { PauseState::FullPause => constants::FullPause } } + diff --git a/cairo/src/lib.cairo b/cairo/src/lib.cairo index 565878b..5bc7274 100644 --- a/cairo/src/lib.cairo +++ b/cairo/src/lib.cairo @@ -1,29 +1,21 @@ -// pub mod interfaces{ -// mod IPausable; -// mod IBlackListed; -// } -// pub mod components{ -// mod BlackListed; -// mod Pausable; -// } pub mod components { - pub mod AccessRegistry; pub mod Pausable; pub mod BlackListed; - pub mod SuperAdmin2Step; } - pub mod contracts{ +pub mod contracts{ + pub mod AccessControl; + pub mod HSTK; pub mod MultisigL2; + } pub mod interfaces { pub mod Ipausable; pub mod IblackListed; pub mod IaccessRegistry; - pub mod IsuperAdmin2Step; } pub mod helpers { pub mod constants; From 976a958718942fef881afe13f4dcb0e14958751c Mon Sep 17 00:00:00 2001 From: Saurabh Date: Tue, 19 Nov 2024 21:46:25 +0530 Subject: [PATCH 7/8] [Feature] added batch logic and removed cairo impl --- cairo/.gitignore | 1 - cairo/.tool-versions | 2 - cairo/Scarb.lock | 20 - cairo/Scarb.toml | 23 - cairo/src/components/AccessRegistry.cairo | 269 ------------ cairo/src/components/BlackListed.cairo | 85 ---- cairo/src/components/Pausable.cairo | 125 ------ cairo/src/components/SuperAdmin2Step.cairo | 185 -------- cairo/src/contracts/AccessControl.cairo | 230 ---------- cairo/src/contracts/HSTK.cairo | 229 ---------- cairo/src/contracts/Multisig.cairo | 412 ------------------ cairo/src/contracts/MultisigL2.cairo | 409 ----------------- cairo/src/helpers/constants.cairo | 3 - cairo/src/interfaces/IaccessRegistry.cairo | 19 - cairo/src/interfaces/IblackListed.cairo | 7 - cairo/src/interfaces/Ipausable.cairo | 25 -- cairo/src/interfaces/IsuperAdmin2Step.cairo | 12 - cairo/src/lib.cairo | 24 - .../src/AccessRegistry/AccessRegistry.sol | 112 +++-- solidity/src/MultiSigWallet.sol | 83 +++- .../IOptimismMintableERC20.sol | 3 +- .../OptimisticStack/OptimismMintableERC20.sol | 116 +---- solidity/test/MultiSig.t.sol | 75 +++- .../mock/MultiSigWallet.sol} | 158 +++---- 24 files changed, 279 insertions(+), 2348 deletions(-) delete mode 100644 cairo/.gitignore delete mode 100644 cairo/.tool-versions delete mode 100644 cairo/Scarb.lock delete mode 100644 cairo/Scarb.toml delete mode 100644 cairo/src/components/AccessRegistry.cairo delete mode 100644 cairo/src/components/BlackListed.cairo delete mode 100644 cairo/src/components/Pausable.cairo delete mode 100644 cairo/src/components/SuperAdmin2Step.cairo delete mode 100644 cairo/src/contracts/AccessControl.cairo delete mode 100644 cairo/src/contracts/HSTK.cairo delete mode 100644 cairo/src/contracts/Multisig.cairo delete mode 100644 cairo/src/contracts/MultisigL2.cairo delete mode 100644 cairo/src/helpers/constants.cairo delete mode 100644 cairo/src/interfaces/IaccessRegistry.cairo delete mode 100644 cairo/src/interfaces/IblackListed.cairo delete mode 100644 cairo/src/interfaces/Ipausable.cairo delete mode 100644 cairo/src/interfaces/IsuperAdmin2Step.cairo delete mode 100644 cairo/src/lib.cairo rename solidity/{src/OptimisticStack/MultiSigL2.sol => test/mock/MultiSigWallet.sol} (74%) diff --git a/cairo/.gitignore b/cairo/.gitignore deleted file mode 100644 index eb5a316..0000000 --- a/cairo/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target diff --git a/cairo/.tool-versions b/cairo/.tool-versions deleted file mode 100644 index d141e39..0000000 --- a/cairo/.tool-versions +++ /dev/null @@ -1,2 +0,0 @@ -starknet-foundry 0.23.0 -scarb 2.6.3 diff --git a/cairo/Scarb.lock b/cairo/Scarb.lock deleted file mode 100644 index 905bedc..0000000 --- a/cairo/Scarb.lock +++ /dev/null @@ -1,20 +0,0 @@ -# Code generated by scarb DO NOT EDIT. -version = 1 - -[[package]] -name = "cairo" -version = "0.1.0" -dependencies = [ - "openzeppelin", - "snforge_std", -] - -[[package]] -name = "openzeppelin" -version = "0.13.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.13.0#978b4e75209da355667d8954d2450e32bd71fe49" - -[[package]] -name = "snforge_std" -version = "0.23.0" -source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.23.0#f2bff8f796763ada77fe6033ec1b034ceee22abd" diff --git a/cairo/Scarb.toml b/cairo/Scarb.toml deleted file mode 100644 index 092acfc..0000000 --- a/cairo/Scarb.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "cairo" -version = "0.1.0" -edition = "2023_11" - -# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html - -# ... - -[dependencies] -starknet = "2.6.3" -openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.13.0" } - -[dev-dependencies] -snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.23.0" } - - - -[[target.starknet-contract]] -sierra = true -casm = true - - diff --git a/cairo/src/components/AccessRegistry.cairo b/cairo/src/components/AccessRegistry.cairo deleted file mode 100644 index a3477b6..0000000 --- a/cairo/src/components/AccessRegistry.cairo +++ /dev/null @@ -1,269 +0,0 @@ - -#[starknet::component] -pub mod AccessRegistryComp { - use starknet::{get_caller_address,get_block_timestamp}; - use starknet::ContractAddress; - use cairo::interfaces::IaccessRegistry::IAccessRegistry; - // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp::SuperAdminTwoStepImpl; - // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp::InternalImpl; - // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp; - use core::num::traits::Zero; - // use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; - // use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; - use openzeppelin_introspection::src5::SRC5Component::InternalImpl as SRC5InternalImpl; - use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; - use openzeppelin_introspection::src5::SRC5Component; - - #[storage] - pub struct Storage { - pub super_admin: ContractAddress, - pub pending_admin: ContractAddress, - pub signers: LegacyMap::, - pub handover_expires: u64, - pub total_signer: u64, - } - - #[event] - #[derive(Drop,PartialEq, starknet::Event)] - pub enum Event { - SignerAdded: SignerAdded, - SignerRemoved: SignerRemoved, - SignerRenounced: SignerRenounced, - SuperOwnershipTransferred: SuperOwnershipTransferred, - SuperOwnershipTransferStarted: SuperOwnershipTransferStarted - } - - #[derive(Drop,PartialEq, starknet::Event)] - pub struct SignerAdded { - #[key] - signer: ContractAddress - } - - #[derive(Drop,PartialEq, starknet::Event)] - pub struct SignerRemoved { - #[key] - signer: ContractAddress - } - - #[derive(Drop,PartialEq, starknet::Event)] - pub struct SignerRenounced { - from: ContractAddress, - to: ContractAddress - } - #[derive(Drop,PartialEq, starknet::Event)] - pub struct SuperOwnershipTransferred { - previous_super_admin: ContractAddress, - new_super_admin: ContractAddress, - } - - #[derive(Drop,PartialEq, starknet::Event)] - pub struct SuperOwnershipTransferStarted { - previous_super_admin: ContractAddress, - new_super_admin: ContractAddress, - } - - pub mod Error { - pub const ZERO_ADDRESS: felt252 = 'Zero Address'; - pub const SuperAdminIsRestricted: felt252 = 'Super Admin Is Restricted'; - pub const Already_Signer: felt252 = 'Already a Signer'; - pub const SuperAdminCannotRemoved: felt252 = 'Super Admin Cannot Removed'; - pub const NonExistingSigner: felt252 = 'Non Existing Signer'; - pub const NOT_OWNER: felt252 = 'Caller is not super admin'; - pub const NOT_PENDING_OWNER: felt252 = 'Caller not pending super admin'; - pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; - pub const HANDOVER_EXPIRED: felt252 = 'Super Admin Ownership expired'; - } - - - #[embeddable_as(AccessRegistry)] - impl AccessRegistyImpl< - TContractState,+HasComponent,+Drop, - +SRC5Component::HasComponent, - > of super::IAccessRegistry> { - - fn is_signer(self: @ComponentState, account: ContractAddress) -> bool { - self.signers.read(account) - } - fn get_total_signer(self:@ComponentState)->u64{ - self.total_signer.read() - } - - fn add_signer(ref self: ComponentState, new_signer: ContractAddress) { - assert(!new_signer.is_zero(), Error::ZERO_ADDRESS); - assert(!self.is_signer(new_signer), Error::Already_Signer); - - // let super_admin_comp = get_dep_component!(@self, SuperAdminTwoStepImpl); - self.assert_only_super_admin(); - self.signers.write(new_signer, true); - self.total_signer.write(self.total_signer.read() + 1); - self.emit(SignerAdded { signer: new_signer }); - } - - fn remove_signer( - ref self: ComponentState, existing_owner: ContractAddress - ) { - assert(!existing_owner.is_zero(), Error::ZERO_ADDRESS); - assert(self.is_signer(existing_owner), Error::NonExistingSigner); - - let super_admin: ContractAddress = self.super_admin.read(); - assert(existing_owner != super_admin, Error::SuperAdminCannotRemoved); - self.assert_only_super_admin(); - - self.signers.write(existing_owner, false); - self.total_signer.write(self.total_signer.read() - 1); - - self.emit(SignerRemoved { signer: existing_owner }); - } - fn renounce_signership(ref self: ComponentState, signer: ContractAddress) { - assert(!signer.is_zero(), Error::ZERO_ADDRESS); //check for zero address - - let caller: ContractAddress = get_caller_address(); - assert(self.is_signer(caller), Error::NonExistingSigner); //only be calleable by signer - assert( - !self.is_signer(signer), Error::Already_Signer - ); //new signer cannot be existing signer - - let super_admin: ContractAddress = self.super_admin.read(); - assert(caller != super_admin, Error::SuperAdminCannotRemoved); //signer cannot be remove - // check it needs to be existing owner - self._renounce_signership(caller, signer); - } - - fn accept_super_adminship(ref self: ComponentState){ - let caller: ContractAddress = get_caller_address(); - let super_admin:ContractAddress = self.super_admin.read(); - self._accept_super_adminship(); - self._renounce_signership(caller,super_admin); - } - - fn get_super_admin(self: @ComponentState) -> ContractAddress { - self.super_admin.read() - } - - /// Returns the address of the pending super_admin. - fn pending_super_admin(self: @ComponentState) -> ContractAddress { - self.pending_admin.read() - } - - //Returns the handover expiry of the pending super_admin - fn super_handover_expires_at(self: @ComponentState) -> u64 { - self.handover_expires.read() - } - - - /// Starts the two-step super_adminship transfer process by setting the pending super_admin. - /// - /// Requirements: - /// - /// - The caller is the contract super_admin. - /// - /// Emits an `OwnershipTransferStarted` event. - fn transfer_super_adminship( - ref self: ComponentState, new_super_admin: ContractAddress - ) { - self.assert_only_super_admin(); - self._propose_super_admin(new_super_admin); - } - - /// Returns the time for which handover is valid for pending super_admin. - fn super_admin_ownership_valid_for(self: @ComponentState) -> u64 { - 72 * 3600 - } - - } - - #[generate_trait] - pub impl InternalImpl< - TContractState, +HasComponent,+Drop, - impl SRC5: SRC5Component::HasComponent, - > of InternalTrait { - - /// Sets the contract's initial super_admin. - /// - /// This function should be called at construction time. - fn initializer(ref self: ComponentState, super_admin: ContractAddress) { - self.super_admin(super_admin); - self.total_signer.write(1); - self.signers.write(super_admin, true); - let mut src5_component = get_dep_component_mut!(ref self, SRC5); - src5_component.register_interface(IaccessRegistry::IACCESSCONTROL_ID); - } - - fn _renounce_signership( - ref self: ComponentState, _from: ContractAddress, _to: ContractAddress - ) { - self.signers.write(_from, false); - self.signers.write(_to, true); - - self.emit(SignerRenounced { from: _from, to: _to }); - } - /// Panics if called by any account other than the super_admin. Use this - /// to restrict access to certain functions to the super_admin. - fn assert_only_super_admin(self: @ComponentState) { - let super_admin = self.super_admin.read(); - let caller = get_caller_address(); - assert(!caller.is_zero(), Error::ZERO_ADDRESS_CALLER); - assert(caller == super_admin, Error::NOT_OWNER); - } - - /// Finishes the two-step super_adminship transfer process by accepting the super_adminship. - /// Can only be called by the pending super_admin. - /// - /// Requirements: - /// - /// - The caller is the pending super_admin. - /// - /// Emits an `OwnershipTransferred` event. - fn _accept_super_adminship(ref self: ComponentState) { - let caller = get_caller_address(); - let pending_super_admin = self.pending_admin.read(); - let super_adminship_expires_at: u64 = self.handover_expires.read(); - assert(caller == pending_super_admin, Error::NOT_PENDING_OWNER); - assert(get_block_timestamp() <= super_adminship_expires_at, Error::HANDOVER_EXPIRED); - self._transfer_super_adminship(pending_super_admin); - } - - /// Transfers super_adminship of the contract to a new address and resets - /// the pending super_admin to the zero address. - /// - /// Internal function without access restriction. - /// - /// Emits an `OwnershipTransferred` event. - fn _transfer_super_adminship( - ref self: ComponentState, new_super_admin: ContractAddress - ) { - self.pending_admin.write(Zero::zero()); - self.handover_expires.write(0); - - let previous_super_admin: ContractAddress = self.super_admin.read(); - self.super_admin.write(new_super_admin); - self - .emit( - SuperOwnershipTransferred { - previous_super_admin: previous_super_admin, new_super_admin: new_super_admin - } - ); - } - - /// Sets a new pending super_admin. - /// - /// Internal function without access restriction. - /// - /// Emits an `OwnershipTransferStarted` event. - fn _propose_super_admin( - ref self: ComponentState, new_super_admin: ContractAddress - ) { - let previous_super_admin = self.super_admin.read(); - self.pending_admin.write(new_super_admin); - let super_adminship_expires_at = get_block_timestamp() - + 72 * 3600; - self.handover_expires.write(super_adminship_expires_at); - self - .emit( - SuperOwnershipTransferStarted { - previous_super_admin: previous_super_admin, new_super_admin: new_super_admin - } - ); - } - } -} diff --git a/cairo/src/components/BlackListed.cairo b/cairo/src/components/BlackListed.cairo deleted file mode 100644 index c09ce6f..0000000 --- a/cairo/src/components/BlackListed.cairo +++ /dev/null @@ -1,85 +0,0 @@ -use starknet::{ContractAddress, get_caller_address}; -use core::traits::Into; -use core::option::OptionTrait; - -#[starknet::component] -pub mod BlackListedComp { - use core::num::traits::zero::Zero; - use cairo::interfaces::IblackListed::IBlackListedComponent; - use starknet::{ContractAddress, get_caller_address}; - use core::traits::Into; - - #[storage] - struct Storage { - blacklisted_account: LegacyMap::, - multi_sig: ContractAddress, - } - - #[event] - #[derive(Drop, starknet::Event)] - pub enum Event { - NewAccountBlackListed: NewAccountBlackListed, - RemovedAccountBlackListed: RemovedAccountBlackListed, - } - - #[derive(Drop, starknet::Event)] - pub struct NewAccountBlackListed { - #[key] - blacklisted_account: ContractAddress - } - - #[derive(Drop, starknet::Event)] - pub struct RemovedAccountBlackListed { - #[key] - removed_account: ContractAddress - } - - mod errors { - pub const ACCOUNT_BLACKLISTED: felt252 = 'Account is BlackListed'; - pub const RESTRICTED_TO_MULTISIG: felt252 = 'Restricted To MultiSig Contract'; - pub const ZERO_ADDRESS: felt252 = 'Calldata consist Zero Address'; - } - - #[embeddable_as(BlackListed)] - impl BlackListedImpl< - TContractState, +HasComponent - > of IBlackListedComponent> { - fn is_blacklisted_account( - self: @ComponentState, account: ContractAddress - ) -> bool { - self.blacklisted_account.read(account) - } - fn blacklist_account(ref self: ComponentState, account: ContractAddress) { - self._only_multi_sig(); - self.blacklisted_account.write(account, true); - self.emit(NewAccountBlackListed { blacklisted_account: account }); - } - - fn remove_blacklisted_account( - ref self: ComponentState, account: ContractAddress - ) { - self._only_multi_sig(); - self.blacklisted_account.write(account, false); - self.emit(RemovedAccountBlackListed { removed_account: account }); - } - } - - #[generate_trait] - pub impl InternalImpl< - TContractState, +HasComponent - > of InternalTrait { - fn initializer(ref self: ComponentState, multi_sig: ContractAddress) { - assert(multi_sig.is_zero(), errors::ZERO_ADDRESS); - self.multi_sig.write(multi_sig); - } - - fn _only_multi_sig(self: @ComponentState) { - assert(get_caller_address() == self.multi_sig.read(), errors::RESTRICTED_TO_MULTISIG); - } - - fn _not_blacklisted(self: @ComponentState, check: ContractAddress) { - let flag: bool = self.blacklisted_account.read(check); - assert(!flag, errors::ACCOUNT_BLACKLISTED); - } - } -} diff --git a/cairo/src/components/Pausable.cairo b/cairo/src/components/Pausable.cairo deleted file mode 100644 index 1aafa32..0000000 --- a/cairo/src/components/Pausable.cairo +++ /dev/null @@ -1,125 +0,0 @@ -// use starknet::ContractAddress; -// use starknet::{get_caller_address, get_contract_address}; -// use starknet::storage_access::StorageAccess; -// use starknet::storage_access::StorageBaseAddress; -// use starknet::SyscallResult; - -// #[starknet::interface] -// pub trait IPausable { -// fn get_current_state(self: @TContractState) -> PauseState; -// fn is_active(self: @TContractState) -> bool; -// fn is_partial_paused(self: @TContractState) -> bool; -// fn is_full_paused(self: @TContractState) -> bool; -// } - -// #[derive(Drop, Copy, Serde, PartialEq)] -// #[repr(felt252)] -// pub enum PauseState { -// Active, -// PartialPause, -// FullPause -// } - -// // Implement StorageAccess for PauseState -// impl StorageAccessPauseState of StorageAccess { -// fn read(address_domain: u32, base: StorageBaseAddress) -> SyscallResult { -// let val = StorageAccess::::read(address_domain, base)?; -// match val { -// 0 => Result::Ok(PauseState::Active), -// 1 => Result::Ok(PauseState::PartialPause), -// 2 => Result::Ok(PauseState::FullPause), -// _ => Result::Err(array!['Invalid PauseState value']) -// } -// } - -// fn write(address_domain: u32, base: StorageBaseAddress, value: PauseState) -> SyscallResult<()> { -// let val = match value { -// PauseState::Active => 0, -// PauseState::PartialPause => 1, -// PauseState::FullPause => 2, -// }; -// StorageAccess::::write(address_domain, base, val) -// } - -// fn size() -> u8 { -// 1 -// } -// } - -// #[starknet::component] -// pub mod pausable_component { -// use super::{PauseState, IPausable}; -// use starknet::{get_caller_address, ContractAddress}; - -// #[storage] -// struct Storage { -// current_state: PauseState, -// } - -// #[event] -// #[derive(Drop, starknet::Event)] -// pub enum Event { -// PauseStateChanged: PauseStateChanged -// } - -// #[derive(Drop, starknet::Event)] -// pub struct PauseStateChanged { -// #[key] -// pub caller: ContractAddress, -// pub new_state: PauseState, -// } - -// #[generate_trait] -// pub trait InternalTrait { -// fn _assert_active(self: @ComponentState); -// fn _assert_not_full_paused(self: @ComponentState); -// fn _update_state(ref self: ComponentState, new_state: PauseState); -// fn initializer(ref self: ComponentState); -// } - -// #[generate_trait] -// impl InternalImpl of InternalTrait { -// fn _assert_active(self: @ComponentState) { -// let state = self.current_state.read().unwrap(); -// assert(state == PauseState::Active, 'Contract must be active'); -// } - -// fn _assert_not_full_paused(self: @ComponentState) { -// let state = self.current_state.read().unwrap(); -// assert(state != PauseState::FullPause, 'Contract must not be fully paused'); -// } - -// fn _update_state(ref self: ComponentState, new_state: PauseState) { -// self.current_state.write(new_state).unwrap(); -// self.emit(Event::PauseStateChanged(PauseStateChanged { -// caller: get_caller_address(), -// new_state -// })); -// } - -// fn initializer(ref self: ComponentState) { -// self.current_state.write(PauseState::Active).unwrap(); -// } -// } - -// #[embeddable_as(IPausableImpl)] -// impl PausableImpl< -// TContractState, impl TContractStateHasComponent: HasComponent -// > of IPausable> { -// fn get_current_state(self: @ComponentState) -> PauseState { -// self.current_state.read().unwrap() -// } - -// fn is_active(self: @ComponentState) -> bool { -// self.current_state.read().unwrap() == PauseState::Active -// } - -// fn is_partial_paused(self: @ComponentState) -> bool { -// self.current_state.read().unwrap() == PauseState::PartialPause -// } - -// fn is_full_paused(self: @ComponentState) -> bool { -// self.current_state.read().unwrap() == PauseState::FullPause -// } -// } -// } \ No newline at end of file diff --git a/cairo/src/components/SuperAdmin2Step.cairo b/cairo/src/components/SuperAdmin2Step.cairo deleted file mode 100644 index d141029..0000000 --- a/cairo/src/components/SuperAdmin2Step.cairo +++ /dev/null @@ -1,185 +0,0 @@ -// // SPDX-License-Identifier: MIT -// // OpenZeppelin Contracts for Cairo v0.19.0 (access/ownable/ownable.cairo) - -// /// # Ownable Component -// /// -// /// The Ownable component provides a basic access control mechanism, where -// /// there is an account (an super_admin) that can be granted exclusive access to -// /// specific functions. -// /// -// /// The initial super_admin can be set by using the `initializer` function in -// /// construction time. This can later be changed with `transfer_super_adminship`. -// /// -// /// The component also offers functionality for a two-step super_adminship -// /// transfer where the new super_admin first has to accept their super_adminship to -// /// finalize the transfer. -// #[starknet::component] -// pub mod SuperAdminTwoStepComp { -// use core::num::traits::Zero; -// use cairo::interfaces::IsuperAdmin2Step::ISuperAdminTwoStep; -// // use cairo_starknet::interfaces::IsuperAdmin2Step; -// use cairo::interfaces::IsuperAdmin2Step; - -// use starknet::ContractAddress; -// use starknet::{get_caller_address, get_block_timestamp}; - -// #[storage] -// pub struct Storage { -// pub super_admin: ContractAddress, -// pub pending_admin: ContractAddress, -// pub handover_expires: u64 -// } - -// #[event] -// #[derive(Drop, PartialEq, starknet::Event)] -// pub enum Event { -// SuperOwnershipTransferred: SuperOwnershipTransferred, -// SuperOwnershipTransferStarted: SuperOwnershipTransferStarted -// } - -// #[derive(Drop, PartialEq, starknet::Event)] -// pub struct SuperOwnershipTransferred { -// #[key] -// pub previous_super_admin: ContractAddress, -// #[key] -// pub new_super_admin: ContractAddress, -// } - -// #[derive(Drop, PartialEq, starknet::Event)] -// pub struct SuperOwnershipTransferStarted { -// #[key] -// pub previous_super_admin: ContractAddress, -// #[key] -// pub new_super_admin: ContractAddress, -// } - -// pub mod Errors { -// pub const NOT_OWNER: felt252 = 'Caller is not super admin'; -// pub const NOT_PENDING_OWNER: felt252 = 'Caller not pending super admin'; -// pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; -// pub const ZERO_ADDRESS_OWNER: felt252 = 'Calldata consist zero address'; -// pub const HANDOVER_EXPIRED: felt252 = 'Super Admin Ownership expired'; -// } - -// /// Adds support for two step super_adminship transfer. -// #[embeddable_as(SuperAdminTwoStepImpl)] -// pub impl SuperAdminTwoStep< -// TContractState, +HasComponent, +Drop -// > of IsuperAdmin2Step::ISuperAdminTwoStep> { -// /// Returns the address of the current super_admin. -// fn super_admin(self: @ComponentState) -> ContractAddress { -// self.super_admin.read() -// } - -// /// Returns the address of the pending super_admin. -// fn pending_super_admin(self: @ComponentState) -> ContractAddress { -// self.pending_admin.read() -// } - -// //Returns the handover expiry of the pending super_admin -// fn super_handover_expires_at(self: @ComponentState) -> u64 { -// self.handover_expires.read() -// } - - -// /// Starts the two-step super_adminship transfer process by setting the pending super_admin. -// /// -// /// Requirements: -// /// -// /// - The caller is the contract super_admin. -// /// -// /// Emits an `OwnershipTransferStarted` event. -// fn transfer_super_adminship( -// ref self: ComponentState, new_super_admin: ContractAddress -// ) { -// self.assert_only_super_admin(); -// self._propose_super_admin(new_super_admin); -// } - -// /// Returns the time for which handover is valid for pending super_admin. -// fn super_admin_ownership_valid_for(self: @ComponentState) -> u64 { -// 72 * 3600 -// } -// } - -// #[generate_trait] -// pub impl InternalImpl< -// TContractState, +HasComponent -// > of InternalTrait { -// /// Sets the contract's initial super_admin. -// /// -// /// This function should be called at construction time. -// fn initializer(ref self: ComponentState, super_admin: ContractAddress) { -// self._transfer_super_adminship(super_admin); -// } - -// /// Panics if called by any account other than the super_admin. Use this -// /// to restrict access to certain functions to the super_admin. -// fn assert_only_super_admin(self: @ComponentState) { -// let super_admin = self.super_admin.read(); -// let caller = get_caller_address(); -// assert(!caller.is_zero(), Errors::ZERO_ADDRESS_CALLER); -// assert(caller == super_admin, Errors::NOT_OWNER); -// } - -// /// Finishes the two-step super_adminship transfer process by accepting the super_adminship. -// /// Can only be called by the pending super_admin. -// /// -// /// Requirements: -// /// -// /// - The caller is the pending super_admin. -// /// -// /// Emits an `OwnershipTransferred` event. -// fn _accept_super_adminship(ref self: ComponentState) { -// let caller = get_caller_address(); -// let pending_super_admin = self.pending_admin.read(); -// let super_adminship_expires_at: u64 = self.handover_expires.read(); -// assert(caller == pending_super_admin, Errors::NOT_PENDING_OWNER); -// assert(get_block_timestamp() <= super_adminship_expires_at, Errors::HANDOVER_EXPIRED); -// self._transfer_super_adminship(pending_super_admin); -// } - -// /// Transfers super_adminship of the contract to a new address and resets -// /// the pending super_admin to the zero address. -// /// -// /// Internal function without access restriction. -// /// -// /// Emits an `OwnershipTransferred` event. -// fn _transfer_super_adminship( -// ref self: ComponentState, new_super_admin: ContractAddress -// ) { -// self.pending_admin.write(Zero::zero()); -// self.handover_expires.write(0); - -// let previous_super_admin: ContractAddress = self.super_admin.read(); -// self.super_admin.write(new_super_admin); -// self -// .emit( -// SuperOwnershipTransferred { -// previous_super_admin: previous_super_admin, new_super_admin: new_super_admin -// } -// ); -// } - -// /// Sets a new pending super_admin. -// /// -// /// Internal function without access restriction. -// /// -// /// Emits an `OwnershipTransferStarted` event. -// fn _propose_super_admin( -// ref self: ComponentState, new_super_admin: ContractAddress -// ) { -// let previous_super_admin = self.super_admin.read(); -// self.pending_admin.write(new_super_admin); -// let super_adminship_expires_at = get_block_timestamp() -// + 72 * 3600; -// self.handover_expires.write(super_adminship_expires_at); -// self -// .emit( -// SuperOwnershipTransferStarted { -// previous_super_admin: previous_super_admin, new_super_admin: new_super_admin -// } -// ); -// } -// } -// } diff --git a/cairo/src/contracts/AccessControl.cairo b/cairo/src/contracts/AccessControl.cairo deleted file mode 100644 index d16d321..0000000 --- a/cairo/src/contracts/AccessControl.cairo +++ /dev/null @@ -1,230 +0,0 @@ -#[starknet::component] -pub mod AccessControlComponent{ - use starknet::{ContractAddress,get_block_timestamp,get_caller_address}; - use cairo::interfaces::IaccessRegistry::IAccessRegistry; - use core::num::traits::Zero; - - #[storage] - pub struct Storage{ - pub Super_admin: ContractAddress, - pub Pending_admin: ContractAddress, - pub Signers: LegacyMap::, - pub Handover_expires: u64, - pub Total_signer: u64, - } - - #[event] - #[derive(Drop,PartialEq, starknet::Event)] - pub enum Event{ - SignerAdded: SignerAdded, - SignerRemoved: SignerRemoved, - SuperOwnershipTransferred: SuperOwnershipTransferred, - SuperOwnershipTransferStarted: SuperOwnershipTransferStarted - } - - #[derive(Drop,PartialEq, starknet::Event)] - pub struct SignerAdded { - pub signer: ContractAddress - } - - #[derive(Drop,PartialEq, starknet::Event)] - pub struct SignerRemoved { - pub signer: ContractAddress - } - #[derive(Drop,PartialEq, starknet::Event)] - pub struct SuperOwnershipTransferred { - pub previous_super_admin: ContractAddress, - pub new_super_admin: ContractAddress, - } - - #[derive(Drop,PartialEq, starknet::Event)] - pub struct SuperOwnershipTransferStarted { - pub previous_super_admin: ContractAddress, - pub new_super_admin: ContractAddress, - } - - pub mod Errors { - pub const ZERO_ADDRESS: felt252 = 'Zero Address'; - pub const SuperAdminIsRestricted: felt252 = 'Super Admin Is Restricted'; - pub const Already_Signer: felt252 = 'Already a Signer'; - pub const SuperAdminCannotRemoved: felt252 = 'Super Admin Cannot Removed'; - pub const NonExistingSigner: felt252 = 'Non Existing Signer'; - pub const NOT_OWNER: felt252 = 'Caller is not super admin'; - pub const NOT_PENDING_OWNER: felt252 = 'Caller not pending super admin'; - pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; - pub const HANDOVER_EXPIRED: felt252 = 'Super Admin Ownership expired'; - } - - #[embeddable_as(AccessControlImpl)] - impl AccessControl< - TContractState, - +HasComponent, - +Drop - > of IAccessRegistry>{ - - fn is_signer(self: @ComponentState, account: ContractAddress)-> bool{ - self.Signers.read(account) - } - fn get_total_signer(self:@ComponentState)->u64{ - self.Total_signer.read() - } - fn add_signer(ref self: ComponentState, new_signer: ContractAddress) { - assert(!new_signer.is_zero(), Errors::ZERO_ADDRESS); - assert(!self.Signers.read(new_signer), Errors::Already_Signer); - - // let super_admin_comp = get_dep_component!(@self, SuperAdminTwoStepImpl); - self.assert_only_super_admin(); - self.Signers.write(new_signer, true); - self.Total_signer.write(self.Total_signer.read() + 1); - self.emit(SignerAdded { signer: new_signer }); - } - - fn remove_signer( - ref self: ComponentState, existing_owner: ContractAddress - ) { - assert(!existing_owner.is_zero(), Errors::ZERO_ADDRESS); - assert(self.Signers.read(existing_owner), Errors::NonExistingSigner); - - let super_admin: ContractAddress = self.Super_admin.read(); - assert(existing_owner != super_admin, Errors::SuperAdminCannotRemoved); - self.assert_only_super_admin(); - - self.Signers.write(existing_owner, false); - self.Total_signer.write(self.Total_signer.read() - 1); - - self.emit(SignerRemoved { signer: existing_owner }); - } - fn renounce_signership(ref self: ComponentState, signer: ContractAddress) { - assert(!signer.is_zero(), Errors::ZERO_ADDRESS); //check for zero address - - let caller: ContractAddress = get_caller_address(); - assert(self.Signers.read(caller), Errors::NonExistingSigner); //only be calleable by signer - assert( - !self.Signers.read(signer), Errors::Already_Signer - ); //new signer cannot be existing signer - - let super_admin: ContractAddress = self.Super_admin.read(); - assert(caller != super_admin, Errors::SuperAdminCannotRemoved); //signer cannot be remove - // check it needs to be existing owner - self._renounce_signership(caller, signer); - } - - fn accept_super_adminship(ref self: ComponentState){ - let caller: ContractAddress = get_caller_address(); - let super_admin:ContractAddress = self.Super_admin.read(); - self._accept_super_adminship(); - self._renounce_signership(caller,super_admin); - } - fn get_super_admin(self: @ComponentState) -> ContractAddress { - self.Super_admin.read() - } - - /// Returns the address of the pending super_admin. - fn pending_super_admin(self: @ComponentState) -> ContractAddress { - self.Pending_admin.read() - } - - //Returns the handover expiry of the pending super_admin - fn super_handover_expires_at(self: @ComponentState) -> u64 { - self.Handover_expires.read() - } - - - /// Starts the two-step super_adminship transfer process by setting the pending super_admin. - /// - /// Requirements: - /// - /// - The caller is the contract super_admin. - /// - /// Emits an `OwnershipTransferStarted` event. - fn transfer_super_adminship( - ref self: ComponentState, new_super_admin: ContractAddress - ) { - self.assert_only_super_admin(); - self._propose_super_admin(new_super_admin); - } - - /// Returns the time for which handover is valid for pending super_admin. - fn super_admin_ownership_valid_for(self: @ComponentState) -> u64 { - 72 * 3600 - } - } - - #[generate_trait] - pub impl InternalImpl< - TContractState, - +HasComponent, - +Drop - > of InternalTrait { - - fn initializer(ref self: ComponentState, super_admin: ContractAddress) { - self.Super_admin.write(super_admin); - self.Total_signer.write(1); - self.Signers.write(super_admin, true); - } - - fn _renounce_signership( - ref self: ComponentState, _from: ContractAddress, _to: ContractAddress - ) { - self.Signers.write(_from, false); - self.Signers.write(_to, true); - - // self.emit(SignerRenounced { from: _from, to: _to }); - } - fn assert_only_super_admin(self: @ComponentState) { - let super_admin = self.Super_admin.read(); - let caller = get_caller_address(); - assert(!caller.is_zero(), Errors::ZERO_ADDRESS_CALLER); - assert(caller == super_admin, Errors::NOT_OWNER); - } - - fn _accept_super_adminship(ref self: ComponentState) { - let caller = get_caller_address(); - let pending_super_admin = self.Pending_admin.read(); - let super_adminship_expires_at: u64 = self.Handover_expires.read(); - assert(caller == pending_super_admin, Errors::NOT_PENDING_OWNER); - assert(get_block_timestamp() <= super_adminship_expires_at, Errors::HANDOVER_EXPIRED); - // self._transfer_super_adminship(pending_super_admin); - } - - fn _transfer_super_adminship( - ref self: ComponentState, new_super_admin: ContractAddress - ) { - self.Pending_admin.write(Zero::zero()); - self.Handover_expires.write(0); - - let previous_super_admin: ContractAddress = self.Super_admin.read(); - self.Super_admin.write(new_super_admin); - self - .emit( - SuperOwnershipTransferred { - previous_super_admin: previous_super_admin, new_super_admin: new_super_admin - } - ); - } - fn _propose_super_admin( - ref self: ComponentState, new_super_admin: ContractAddress - ) { - let previous_super_admin = self.Super_admin.read(); - self.Pending_admin.write(new_super_admin); - let super_adminship_expires_at = get_block_timestamp() - + 72 * 3600; - self.Handover_expires.write(super_adminship_expires_at); - self - .emit( - SuperOwnershipTransferStarted { - previous_super_admin: previous_super_admin, new_super_admin: new_super_admin - } - ); - } - - } - - - - - - - - -} \ No newline at end of file diff --git a/cairo/src/contracts/HSTK.cairo b/cairo/src/contracts/HSTK.cairo deleted file mode 100644 index 4385605..0000000 --- a/cairo/src/contracts/HSTK.cairo +++ /dev/null @@ -1,229 +0,0 @@ -// SPDX-License-Identifier: MIT -use starknet::ContractAddress; - -#[starknet::interface] -pub trait IHashToken{ - - fn permissioned_mint(ref self: TContractState, account: ContractAddress, amount: u256); - fn permissioned_burn(ref self: TContractState, account: ContractAddress, amount: u256); - fn total_supply(self: @TContractState) -> u256; - - fn balance_of(self: @TContractState, account: ContractAddress) -> u256; - - fn allowance( - self: @TContractState, owner: ContractAddress, spender: ContractAddress - ) -> u256; - - fn transfer( - ref self: TContractState, recipient: ContractAddress, amount: u256 - ) -> bool; - - fn transfer_from( - ref self: TContractState, - sender: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) -> bool; - - fn approve( - ref self: TContractState, spender: ContractAddress, amount: u256) -> bool; - - // IERC20Metadata - fn name(self:@TContractState) -> ByteArray; - fn symbol(self:@TContractState) -> ByteArray; - fn decimals(self:@TContractState) -> u8; - - -} -#[starknet::interface] -pub trait IHashTokenCamel{ - - fn permissionedMint(ref self: TContractState, account: ContractAddress, amount: u256); - fn permissionedBurn(ref self: TContractState, account: ContractAddress, amount: u256); - fn totalSupply(self: @TContractState) -> u256; - fn balanceOf(self: @TContractState, account: ContractAddress) -> u256; - fn transferFrom( - ref self: TContractState, - sender: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) -> bool; - -} - -#[starknet::contract] -mod HSTK { - use starknet::{ClassHash, ContractAddress, get_caller_address}; - // use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE}; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use super::IHashToken; - use super::IHashTokenCamel; - // use cairo::components::AccessRegistry::AccessRegistryComp::{InternalImpl,AccessRegistry}; - // use cairo::interfaces::IHashToken::{IHashToken, IHashTokenCamel}; - use cairo::components::BlackListed::BlackListedComp; - component!(path: BlackListedComp, storage: blacklisted, event: BlackListedEvent); - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - - // #[abi(embed_v0)] - // impl AccessControlImpl = access_comp::AccessControlImpl; - // impl AccessControlInternalImpl = access_comp::InternalImpl; - - - impl ERC20MixinImpl = ERC20Component::ERC20Mixin; - - impl ERC20InternalImpl = ERC20Component::InternalImpl; - impl BlackListedInternalImpl = BlackListedComp::InternalImpl; - - #[abi(embed_v0)] - impl BlackListedImpl = BlackListedComp::BlackListed; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20: ERC20Component::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage, - #[substorage(v0)] - blacklisted: BlackListedComp::Storage, - bridge: ContractAddress, - l1_token:ContractAddress - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20Event: ERC20Component::Event, - #[flat] - SRC5Event: SRC5Component::Event, - #[flat] - BlackListedEvent: BlackListedComp::Event, - - } - - #[constructor] - fn constructor( - ref self: ContractState, - default_admin: ContractAddress, - bridge: ContractAddress, - l1_token: ContractAddress, - multi_sig:ContractAddress - ) { - self.erc20.initializer("HSTK", "HSTK"); - self.blacklisted.initializer(multi_sig); - self.l1_token.write(l1_token); - self.bridge.write(bridge); - } - - #[abi(embed_v0)] - impl HashTokenImpl of IHashToken { - fn permissioned_mint(ref self: ContractState, account: ContractAddress, amount: u256) { - self.assert_only_bridge(); - self.erc20._mint(account, amount); - } - fn permissioned_burn(ref self: ContractState, account: ContractAddress, amount: u256) { - self.assert_only_bridge(); - self.erc20._burn(get_caller_address(), amount); - } - fn total_supply(self:@ContractState) -> u256 { - self.erc20.total_supply() - } - - fn balance_of(self: @ContractState, account: ContractAddress) -> u256{ - self.erc20.balance_of(account) - } - - fn allowance( - self: @ContractState, owner: ContractAddress, spender: ContractAddress - ) -> u256 { - self.erc20.allowance(owner, spender) - } - - fn transfer( - ref self: ContractState, recipient: ContractAddress, amount: u256 - ) -> bool { - - self.blacklisted._not_blacklisted(recipient); - self.blacklisted._not_blacklisted(get_caller_address()); - // should be active - self.erc20.transfer(recipient, amount) - } - - fn transfer_from( - ref self: ContractState, - sender: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) -> bool { - - self.blacklisted._not_blacklisted(recipient); - self.blacklisted._not_blacklisted(recipient); - self.erc20.transfer_from(sender, recipient, amount) - } - - fn approve( - ref self: ContractState, spender: ContractAddress, amount: u256 - ) -> bool { - self.blacklisted._not_blacklisted(spender); - self.blacklisted._not_blacklisted(get_caller_address()); - self.erc20.approve(spender, amount) - } - - // IERC20Metadata - fn name(self: @ContractState) -> ByteArray { - self.erc20.name() - } - - fn symbol(self: @ContractState) -> ByteArray { - self.erc20.symbol() - } - - fn decimals(self: @ContractState) -> u8 { - self.erc20.decimals() - } - - } - - #[abi(embed_v0)] - impl HashTokenCamelImpl of IHashTokenCamel { - fn permissionedMint(ref self: ContractState, account: ContractAddress, amount: u256){ - HashTokenImpl::permissioned_mint(ref self, account, amount) - } - fn permissionedBurn(ref self: ContractState, account: ContractAddress, amount: u256) { - HashTokenImpl::permissioned_burn(ref self, account, amount) - } - - // IERC20CamelOnly - fn totalSupply(self: @ContractState) -> u256 { - HashTokenImpl::total_supply(self) - } - - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { - HashTokenImpl::balance_of(self, account) - } - - fn transferFrom( - ref self: ContractState, - sender: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) -> bool { - HashTokenImpl::transfer_from(ref self, sender, recipient, amount) - } - } - - - #[generate_trait] - impl HSTKInternalImpl of InternalTrait { - fn assert_only_bridge(self: @ContractState){ - - let caller = get_caller_address(); - let bridge = self.bridge.read(); - assert(caller == bridge,'Only Bridge'); - - } - } -} \ No newline at end of file diff --git a/cairo/src/contracts/Multisig.cairo b/cairo/src/contracts/Multisig.cairo deleted file mode 100644 index e3df531..0000000 --- a/cairo/src/contracts/Multisig.cairo +++ /dev/null @@ -1,412 +0,0 @@ - -// use starknet::{ContractAddress,ClassHash}; -// #[derive(Copy, Drop, Serde, starknet::Store)] -// pub enum TransactionState { -// Pending, -// Active, -// Queued, -// Expired, -// Executed -// } - -// pub fn resolve_tx_state(state: TransactionState) -> felt252 { -// match state { -// TransactionState::Pending => 0, -// TransactionState::Active => 1, -// TransactionState::Queued => 2, -// TransactionState::Expired => 3, -// TransactionState::Executed => 4, - -// } -// } - -// #[starknet::interface] -// pub trait IMultiSigL2 { -// fn upgrade(ref self: TContractState, new_class_hash: ClassHash); -// fn create_blacklist_tx(ref self:TContractState, account:ContractAddress)->felt252; -// fn create_removeBlacklisted_tx(ref self:TContractState, account:ContractAddress)->felt252; -// fn create_recover_token_tx(ref self: TContractState,asset:ContractAddress, receipient:ContractAddress)->felt252; -// fn update_pauseState_tx(ref self:TContractState,state:u8)->felt252; -// fn update_transaction_state(ref self:TContractState,tx_id:felt252)->TransactionState; -// fn approve_transaction(ref self: TContractState,tx_id:felt252); -// fn revoke_signatory(ref self: TContractState,tx_id:felt252); -// fn execute_transaction(ref self: TContractState,tx_id:felt252); -// fn is_valid_tx(self:@TContractState,tx_id:felt252)->bool; -// } -// #[starknet::contract] -// pub mod MultiSigL2{ - -// use starknet::{ContractAddress,ClassHash,SyscallResultTrait}; -// use starknet::{get_caller_address,get_block_timestamp}; -// // use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; -// use starknet::storage::{ -// StoragePointerReadAccess, StoragePointerWriteAccess, StoragePathEntry -// }; -// use core::array::ArrayTrait; -// use core::option::OptionTrait; -// use cairo::components::AccessRegistry::AccessRegistryComp; -// use cairo::components::AccessRegistry::AccessRegistryComp::{InternalImpl,AccessRegistyImpl}; -// // use cairo::components::AccessRegistry::AccessRegistryComp::AccessRegistyImpl; -// // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp; -// // use cairo::components::SuperAdmin2Step::SuperAdminTwoStep::SuperAdminTwoStepImpl; -// use openzeppelin::upgrades::{UpgradeableComponent, interface::IUpgradeable}; -// use openzeppelin::introspection::src5::SRC5Component; -// use super::{TransactionState,resolve_tx_state}; -// use core::num::traits::Zero; -// use core::pedersen::PedersenTrait; -// use starknet::account::Call; -// use starknet::syscalls::call_contract_syscall; -// use core::starknet::event::EventEmitter; - -// component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); -// component!(path: SRC5Component, storage: src5, event: SRC5Event); -// component!(path: AccessRegistryComp , storage: access_registry , event: AccessRegistryEvent); - - -// /// Upgradeable -// impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl; -// impl AccessRegistryInternalImpl = AccessRegistryComp::InternalImpl; - -// // Constants -// pub const SIGNER_WINDOW: u64 = 86400; // 24 hours in seconds -// pub const APPROVAL_THRESHOLD: u64 = 60; // 60% of signers must approve - -// // Function selectors as constants -// pub const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); -// pub const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); -// pub const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); -// pub const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); - -// #[derive(Drop, Serde,starknet::store)] -// pub struct Transaction { -// proposer: ContractAddress, -// selector: felt252, -// params : Array, -// proposed_at: u64, -// first_sign_at: u64, -// approvals: u64 -// } - -// #[storage] -// struct Storage { - -// #[substorage(v0)] -// upgradeable: UpgradeableComponent::Storage, -// #[substorage(v0)] -// src5: SRC5Component::Storage, -// #[substorage(v0)] -// access_registry: AccessRegistryComp::Storage, -// token_contract: ContractAddress, -// transactions: LegacyMap::, -// has_approved: LegacyMap::<(felt252, ContractAddress), bool>, -// transaction_exists: LegacyMap::, -// signer_functions: LegacyMap::, -// transaction_state: LegacyMap::, -// } - -// #[event] -// #[derive(Drop,starknet::Event)] -// enum Event{ -// TransactionProposed: TransactionProposed, -// TransactionApproved: TransactionApproved, -// SignatoryRevoked: SignatoryRevoked, -// TransactionExecuted: TransactionExecuted, -// TransactionExpired: TransactionExpired, -// TransactionStateChanged: TransactionStateChanged, -// #[flat] -// UpgradeableEvent: UpgradeableComponent::Event, -// #[flat] -// SRC5Event: SRC5Component::Event, -// #[flat] -// AccessRegistryEvent: AccessRegistryComp::Event, -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionProposed { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub proposer:ContractAddress, -// #[key] -// pub proposed_at: u64, -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionApproved { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub signer: ContractAddress, -// } - -// #[derive(Drop,starknet::Event)] -// pub struct SignatoryRevoked { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub revoker: ContractAddress, -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionExecuted { -// #[key] -// pub tx_id: felt252 -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionExpired { -// #[key] -// pub tx_id: felt252 -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionStateChanged { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub new_state: TransactionState, -// } - -// pub mod Error{ -// pub const ZERO_ADDRESS:felt252 = 'CAlldata consist Zero Address'; -// } - -// #[abi(embed_v0)] -// impl AccessRegistyImpl = -// AccessRegistryComp::Access_Registry; - -// #[constructor] -// fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress){ -// assert(!token_l2.is_zero() && !super_admin.is_zero(),Error::ZERO_ADDRESS); -// self.access_registry.initializer(super_admin); -// self.token_contract.write(token_l2); -// } - -// #[abi(embed_v0)] -// impl MultiSigL2Impl of super::IMultiSigL2{ - -// fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { -// self.access_registry.assert_only_super_admin(); -// self.upgradeable.upgrade(new_class_hash); -// } - -// fn create_blacklist_tx(ref self:ContractState, account:ContractAddress)->felt252 { - -// assert(!account.is_zero(),Error::ZERO_ADDRESS); -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let mut calldata:Array = array![]; -// Serde::serialize(@account, ref calldata); -// self._route_standarad_transaction(BLACKLIST_ACCOUNT_SELECTOR,calldata) -// } -// fn create_removeBlacklisted_tx(ref self:ContractState, account:ContractAddress)->felt252{ - -// assert(!account.is_zero(),Error::ZERO_ADDRESS); -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let mut calldata:Array = array![]; -// Serde::serialize(@account, ref calldata); -// self._route_standarad_transaction(REMOVE_BLACKLIST_ACCOUNT_SELECTOR,calldata) - -// } -// fn create_recover_token_tx(ref self: ContractState,asset:ContractAddress, receipient:ContractAddress)->felt252{ - -// assert(!asset.is_zero() &&!receipient.is_zero() ,Error::ZERO_ADDRESS); -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let mut calldata:Array = array![]; -// Serde::serialize(@asset, ref calldata); -// Serde::serialize(@receipient, ref calldata); -// self._route_standarad_transaction(RECOVER_TOKENS_SELECTOR,calldata) - -// } -// fn update_pauseState_tx(ref self:ContractState,state:u8)->felt252{ - -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let mut calldata:Array = array![]; -// Serde::serialize(@state, ref calldata); -// self._route_standarad_transaction(PAUSE_STATE_SELECTOR,calldata) - -// } -// fn update_transaction_state(ref self:ContractState,tx_id:felt252)->TransactionState{ -// self._assert_transaction_exists(tx_id); - -// let mut transaction= self.transactions.read(tx_id); -// let transaction_s = self.transaction_state.read(tx_id); - -// if (transaction_s == TransactionState::Expired){ -// transaction_s -// } -// if(transaction_s == TransactionState::Executed){ -// transaction_s -// } -// let current_time = get_block_timestamp(); - -// let isExpired:bool = current_time > transaction.first_sign_at + SIGNER_WINDOW; - -// let mut new_state:TransactionState = transaction_s; -// let total_signers:u64 = self.access_registry.total_signer(); - -// if(isExpired){ -// if((transaction.approvals * 100) / total_signers >= APPROVAL_THRESHOLD){ -// new_state = TransactionState::Queued; -// }else{ -// //emit an Insufficient Approval Event -// self.emit( -// TransactionExpired{ -// tx_id: tx_id -// } -// ); -// new_state = TransactionState::Expired; -// } -// }else if(transaction.first_sign_at!=0){ -// new_state = TransactionState::Active; -// } - -// if (new_state != transaction_s) { -// self.transaction_state.write(tx_id,new_state); -// // self.(emit{TransactionStateChanged(txId, transaction.state)}); -// } - -// new_state - -// } -// fn is_valid_tx(self:@ContractState,tx_id:felt252)->bool{ -// true -// } - -// fn approve_transaction(ref self: ContractState, tx_id: felt252) { - -// self._assert_transaction_exists(tx_id); -// let caller = get_caller_address(); -// let current_timestamp =get_block_timestamp(); -// assert(self.access_registry.is_signer(caller), 'Not a signer'); -// assert(!self.has_approved.read((tx_id, caller)), 'Already approved'); - -// let mut transaction = self.transactions.read(tx_id); -// let current_state = self.update_transaction_state(tx_id); - -// assert( -// current_state == TransactionState::Pending || -// current_state == TransactionState::Active, -// 'Invalid state' -// ); - -// if transaction.approvals == 0 { -// transaction.first_sign_at = current_timestamp; -// } - -// transaction.approvals += 1 ; -// self.has_approved.write((tx_id, caller), true); -// self.transactions.write(tx_id, transaction); - -// self.emit(TransactionApproved { tx_id, signer: caller }); -// } -// fn revoke_signatory(ref self: ContractState,tx_id:felt252){ - -// self._assert_transaction_exists(tx_id); -// let caller = get_caller_address(); -// let current_timestamp =get_block_timestamp(); -// assert(self.access_registry.is_signer(caller), 'Not a signer'); -// assert(self.has_approved.read((tx_id, caller)), 'Not approved'); - -// let mut transaction = self.transactions.read(tx_id); -// let current_state = self.update_transaction_state(tx_id); - -// assert( -// current_state == TransactionState::Active, -// 'Invalid state for Revoke Signature' -// ); -// transaction.approvals -= 1; -// self.has_approved.write((tx_id, caller), false); -// self.transactions.write(tx_id, transaction); -// self.emit(SignatoryRevoked { tx_id: tx_id, revoker: caller }); - - -// } -// fn execute_transaction(ref self: ContractState, tx_id: felt252) { -// self._assert_transaction_exists(tx_id); -// let mut transaction = self.transactions.read(tx_id); -// let current_state = self.update_transaction_state(tx_id); - -// assert(current_state == TransactionState::Queued, 'Invalid state'); -// self.transaction_state.write(tx_id,TransactionState::Executed); -// // self.transactions.write(tx_id, transaction); -// let function_selector = transaction.selector.clone(); -// let params = transaction.params.clone(); - -// self._call(function_selector, params); -// self.emit(TransactionExecuted { tx_id }); -// } - -// } -// #[generate_trait] -// impl MultiSigInternalImpl of InternalTrait { -// fn _route_standarad_transaction(self: @ContractState, function_selector: felt252 , calldata:Array)->felt252{ -// let caller: ContractAddress = get_caller_address(); -// let super_admin:ContractAddress = self.access_registry.super_admin(); -// if caller==super_admin { -// self._call(function_selector,calldata) -// }else{ -// self._create_transaction(function_selector,calldata) -// } - -// } - -// fn _assert_transaction_exists(self: @ContractState, tx_id: felt252) { -// assert(self.transaction_exists.read(tx_id), 'Transaction not found'); -// } - -// fn _create_transaction( -// ref self: ContractState, -// selector: felt252, -// params: Array -// ) -> felt252 { -// let caller = get_caller_address(); -// let is_signer = self.access_registry.is_signer(caller); -// let timestamp = get_block_timestamp(); -// let is_valid_function:bool = self.signer_functions.read(selector); - -// assert(is_valid_function && is_signer , 'Unauthorized'); - -// // let tx_id = PedersenTrait::new(0).update_with(params).update_with(timestamp).update_with(selector).finalize(); -// let tx_id = get_block_timestamp().into(); - - -// //For multiple transaction with same params andd calldata in a single Block. -// assert(!self.transaction_exists.read(tx_id), 'Transaction exists'); - -// self.transaction_exists.write(tx_id, true); -// let transaction:Transaction = Transaction { -// proposer: caller, -// selector, -// params, -// proposed_at: timestamp, -// first_sign_at: 0, -// approvals: 0 -// }; - -// self.transactions.write(tx_id, transaction); -// self.transaction_state.write(tx_id,TransactionState::Pending); -// self.emit(TransactionProposed { -// tx_id, -// proposer: caller, -// proposed_at: get_block_timestamp() -// }); - -// tx_id -// } - -// fn _call(self:@ContractState, function_selector:felt252, calldata:Array)->felt252{ -// get_block_timestamp().into() - -// } - - -// // const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); -// // const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); -// // const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); -// // const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); - - -// } - -// } - diff --git a/cairo/src/contracts/MultisigL2.cairo b/cairo/src/contracts/MultisigL2.cairo deleted file mode 100644 index 77a51fb..0000000 --- a/cairo/src/contracts/MultisigL2.cairo +++ /dev/null @@ -1,409 +0,0 @@ - -// use starknet::{ContractAddress,ClassHash}; -// #[derive(Copy, Drop, Serde, starknet::Store)] -// pub enum TransactionState { -// Pending, -// Active, -// Queued, -// Expired, -// Executed -// } - -// pub fn resolve_tx_state(state: TransactionState) -> felt252 { -// match state { -// TransactionState::Pending => 0, -// TransactionState::Active => 1, -// TransactionState::Queued => 2, -// TransactionState::Expired => 3, -// TransactionState::Executed => 4, - -// } -// } - -// #[starknet::interface] -// pub trait IMultiSigL2 { -// fn upgrade(ref self: TContractState, new_class_hash: ClassHash); -// fn create_blacklist_tx(ref self:TContractState, account:ContractAddress)->felt252; -// fn create_removeBlacklisted_tx(ref self:TContractState, account:ContractAddress)->felt252; -// fn create_recover_token_tx(ref self: TContractState,asset:ContractAddress, receipient:ContractAddress)->felt252; -// fn update_pauseState_tx(ref self:TContractState,state:u8)->felt252; -// fn update_transaction_state(ref self:TContractState,tx_id:felt252)->TransactionState; -// fn approve_transaction(ref self: TContractState,tx_id:felt252); -// fn revoke_signatory(ref self: TContractState,tx_id:felt252); -// fn execute_transaction(ref self: TContractState,tx_id:felt252); -// fn is_valid_tx(self:@TContractState,tx_id:felt252)->bool; -// } -// #[starknet::contract] -// pub mod MultiSigL2{ - -// use starknet::{ContractAddress,ClassHash,SyscallResultTrait}; -// use starknet::{get_caller_address,get_block_timestamp}; -// // use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; -// use starknet::storage::{ -// StoragePointerReadAccess, StoragePointerWriteAccess, StoragePathEntry -// }; -// use core::array::ArrayTrait; -// use core::option::OptionTrait; -// use cairo::components::AccessRegistry::AccessRegistryComp; -// use cairo::components::AccessRegistry::AccessRegistryComp::{InternalImpl,AccessRegistyImpl}; -// // use cairo::components::AccessRegistry::AccessRegistryComp::AccessRegistyImpl; -// // use cairo::components::SuperAdmin2Step::SuperAdminTwoStepComp; -// // use cairo::components::SuperAdmin2Step::SuperAdminTwoStep::SuperAdminTwoStepImpl; -// use openzeppelin::upgrades::{UpgradeableComponent, interface::IUpgradeable}; -// use openzeppelin::introspection::src5::SRC5Component; -// use super::{TransactionState,resolve_tx_state}; -// use core::num::traits::Zero; -// use core::pedersen::PedersenTrait; -// use starknet::account::Call; -// use starknet::syscalls::call_contract_syscall; -// use core::starknet::event::EventEmitter; - -// component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); -// component!(path: SRC5Component, storage: src5, event: SRC5Event); -// component!(path: AccessRegistryComp , storage: access_registry , event: AccessRegistryEvent); - - -// #[abi(embed_v0)] -// impl AccessRegistyImpl = AccessRegistryComp::Access_Registry; -// /// Upgradeable -// impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl; -// impl AccessRegistryInternalImpl = AccessRegistryComp::InternalImpl; - -// // Constants -// pub const SIGNER_WINDOW: u64 = 86400; // 24 hours in seconds -// pub const APPROVAL_THRESHOLD: u64 = 60; // 60% of signers must approve - -// // Function selectors as constants -// pub const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); -// pub const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); -// pub const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); -// pub const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); - -// #[derive(Drop, Serde,starknet::Store)] -// pub struct Transaction { -// proposer: ContractAddress, -// selector: felt252, -// params : Array, -// proposed_at: u64, -// first_sign_at: u64, -// approvals: u64, -// state: TransactionState -// } - -// #[storage] -// struct Storage { - -// #[substorage(v0)] -// upgradeable: UpgradeableComponent::Storage, -// #[substorage(v0)] -// src5: SRC5Component::Storage, -// #[substorage(v0)] -// access_registry: AccessRegistryComp::Storage, -// token_contract: ContractAddress, -// transactions: LegacyMap::, -// has_approved: LegacyMap::<(felt252, ContractAddress), bool>, -// transaction_exists: LegacyMap::, -// signer_functions: LegacyMap:: -// } - -// #[event] -// #[derive(Drop,starknet::Event)] -// enum Event{ -// TransactionProposed: TransactionProposed, -// TransactionApproved: TransactionApproved, -// SignatoryRevoked: SignatoryRevoked, -// TransactionExecuted: TransactionExecuted, -// TransactionExpired: TransactionExpired, -// TransactionStateChanged: TransactionStateChanged, -// #[flat] -// UpgradeableEvent: UpgradeableComponent::Event, -// #[flat] -// SRC5Event: SRC5Component::Event, -// #[flat] -// AccessRegistryEvent: AccessRegistryComp::Event, -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionProposed { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub proposer:ContractAddress, -// #[key] -// pub proposed_at: u64, -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionApproved { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub signer: ContractAddress, -// } - -// #[derive(Drop,starknet::Event)] -// pub struct SignatoryRevoked { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub revoker: ContractAddress, -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionExecuted { -// #[key] -// pub tx_id: felt252 -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionExpired { -// #[key] -// pub tx_id: felt252 -// } - -// #[derive(Drop,starknet::Event)] -// pub struct TransactionStateChanged { -// #[key] -// pub tx_id: felt252, -// #[key] -// pub new_state: TransactionState, -// } - -// pub mod Error{ -// pub const ZERO_ADDRESS:felt252 = 'CAlldata consist Zero Address'; -// } - - -// #[constructor] -// fn constructor(ref self: ContractState,token_l2:ContractAddress, super_admin:ContractAddress){ -// assert(!token_l2.is_zero() && !super_admin.is_zero(),Error::ZERO_ADDRESS); -// self.access_registry.initializer(super_admin); -// self.token_contract.write(token_l2); -// } - -// #[abi(embed_v0)] -// impl MultiSigL2Impl of super::IMultiSigL2{ - -// fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { -// self.access_registry.assert_only_super_admin(); -// self.upgradeable.upgrade(new_class_hash); -// } - -// fn create_blacklist_tx(ref self:ContractState, account:ContractAddress)->felt252 { - -// assert(!account.is_zero(),Error::ZERO_ADDRESS); -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let calldata:Array = array![account.into()]; -// // Serde::serialize(@account, ref calldata); -// self._route_standarad_transaction(BLACKLIST_ACCOUNT_SELECTOR,calldata) -// } -// fn create_removeBlacklisted_tx(ref self:ContractState, account:ContractAddress)->felt252{ - -// assert(!account.is_zero(),Error::ZERO_ADDRESS); -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let mut calldata:Array = array![account.into()]; -// // Serde::serialize(@account, ref calldata); -// self._route_standarad_transaction(REMOVE_BLACKLIST_ACCOUNT_SELECTOR,calldata) - -// } -// fn create_recover_token_tx(ref self: ContractState,asset:ContractAddress, receipient:ContractAddress)->felt252{ - -// assert(!asset.is_zero() &&!receipient.is_zero() ,Error::ZERO_ADDRESS); -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let mut calldata:Array = array![asset.into(),receipient.into()]; -// // Serde::serialize(@asset, ref calldata); -// // Serde::serialize(@receipient, ref calldata); -// self._route_standarad_transaction(RECOVER_TOKENS_SELECTOR,calldata) - -// } -// fn update_pauseState_tx(ref self:ContractState,state:felt252)->felt252{ - -// assert(!self.access_registry.is_signer(get_caller_address()),'Not Signer'); -// let mut calldata:Array = array![state.into()]; -// // Serde::serialize(@state, ref calldata); -// self._route_standarad_transaction(PAUSE_STATE_SELECTOR,calldata) - -// } -// fn update_transaction_state(ref self:ContractState,tx_id:felt252)->TransactionState{ -// self._assert_transaction_exists(tx_id); -// let mut transaction= self.transactions.read(tx_id); - -// if (resolve_tx_state(transaction.state.read()) == resolve_tx_state(TransactionState::Expired)){ -// transaction.state -// } -// if(resolve_tx_state(transaction.state.read()) == resolve_tx_state(TransactionState::Executed)){ -// transaction.state.read() -// } -// let current_time = get_block_timestamp(); - -// let isExpired:bool = current_time > transaction.first_sign_at.read() + SIGNER_WINDOW; - -// let mut new_state:TransactionState = transaction.state.read(); -// let total_signers:u64 = self.access_registry.total_signer(); - -// if(isExpired){ -// if((transaction.approvals * 100) / total_signers >= APPROVAL_THRESHOLD){ -// new_state = TransactionState::Queued; -// }else{ -// //emit an Insufficient Approval Event -// self.emit( -// TransactionExpired{ -// tx_id: tx_id -// } -// ); -// new_state = TransactionState::Expired; -// } -// }else if(transaction.first_sign_at!=0){ -// new_state = TransactionState::Active; -// } - -// if (resolve_tx_state(new_state) != resolve_tx_state(transaction.state)) { -// transaction.state = new_state; -// // self.(emit{TransactionStateChanged(txId, transaction.state)}); -// } - -// new_state - -// } -// fn is_valid_tx(self:@ContractState,tx_id:felt252)->bool{ -// true -// } - -// fn approve_transaction(ref self: ContractState, tx_id: felt252) { - -// self._assert_transaction_exists(tx_id); -// let caller = get_caller_address(); -// let current_timestamp =get_block_timestamp(); -// assert(self.access_registry.is_signer(caller), 'Not a signer'); -// assert(!self.has_approved.read((tx_id, caller)), 'Already approved'); - -// let mut transaction = self.transactions.read(tx_id); -// let current_state = self.update_transaction_state(tx_id); - -// assert( -// resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Pending) || -// resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Active), -// 'Invalid state' -// ); - -// if transaction.approvals == 0 { -// transaction.first_sign_at = current_timestamp; -// } - -// transaction.approvals.write(transaction.approvals.read()+1); -// self.has_approved.write((tx_id, caller), true); -// self.transactions.write(tx_id, transaction); - -// self.emit(TransactionApproved { tx_id, signer: caller }); -// } -// fn revoke_signatory(ref self: ContractState,tx_id:felt252){ - -// self._assert_transaction_exists(tx_id); -// let caller = get_caller_address(); -// let current_timestamp =get_block_timestamp(); -// assert(self.access_registry.is_signer(caller), 'Not a signer'); -// assert(self.has_approved.read((tx_id, caller)), 'Not approved'); - -// let mut transaction = self.transactions.read(tx_id); -// let current_state = self.update_transaction_state(tx_id); - -// assert( -// resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Active), -// 'Invalid state for Revoke Signature' -// ); -// transaction.approvals.write(transaction.approvals.read()-1); -// self.has_approved.write((tx_id, caller), false); -// self.transactions.write(tx_id, transaction); -// self.emit(SignatoryRevoked { tx_id: tx_id, revoker: caller }); - - -// } -// fn execute_transaction(ref self: ContractState, tx_id: felt252) { -// self._assert_transaction_exists(tx_id); -// let mut transaction = self.transactions.read(tx_id); -// let current_state = self.update_transaction_state(tx_id); - -// assert(resolve_tx_state(current_state) == resolve_tx_state(TransactionState::Queued), 'Invalid state'); -// transaction.state.read() = TransactionState::Executed; -// // self.transactions.write(tx_id, transaction); -// let function_selector = transaction.selector.read(); -// let params = transaction.params.read(); - -// self._call(function_selector, params); -// self.emit(TransactionExecuted { tx_id }); -// } - -// } -// #[generate_trait] -// impl MultiSigInternalImpl of InternalTrait { -// fn _route_standarad_transaction(self: @ContractState, function_selector: felt252 , calldata:Array)->felt252{ -// let caller: ContractAddress = get_caller_address(); -// let super_admin:ContractAddress = self.access_registry.super_admin(); -// if caller==super_admin { -// self._call(function_selector,calldata) -// }else{ -// self._create_transaction(function_selector,calldata) -// } - -// } - -// fn _assert_transaction_exists(self: @ContractState, tx_id: felt252) { -// assert(self.transaction_exists.read(tx_id), 'Transaction not found'); -// } - -// fn _create_transaction( -// ref self: ContractState, -// selector: felt252, -// params: Array -// ) -> felt252 { -// let caller = get_caller_address(); -// let is_signer = self.access_registry.is_signer(caller); -// let timestamp = get_block_timestamp(); -// let is_valid_function:bool = self.signer_functions.read(selector); - -// assert(is_valid_function && is_signer , 'Unauthorized'); - -// // let tx_id = PedersenTrait::new(0).update_with(params).update_with(timestamp).update_with(selector).finalize(); -// let tx_id = get_block_timestamp().into(); - - -// //For multiple transaction with same params andd calldata in a single Block. -// assert(!self.transaction_exists.read(tx_id), 'Transaction exists'); - -// self.transaction_exists.write(tx_id, true); -// let transaction:Transaction = Transaction { -// proposer: caller, -// selector, -// params, -// proposed_at: timestamp, -// first_sign_at: 0, -// approvals: 0, -// state: TransactionState::Pending -// }; - -// self.transactions.write(tx_id, transaction); -// self.emit(TransactionProposed { -// tx_id, -// proposer: caller, -// proposed_at: get_block_timestamp() -// }); - -// tx_id -// } - -// fn _call(self:@ContractState, function_selector:felt252, calldata:Array)->felt252{ -// get_block_timestamp().into() - -// } - - -// // const PAUSE_STATE_SELECTOR: felt252 = selector!("update_pause_state(u8)"); -// // const BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("blacklist_account(ContractAddress)"); -// // const REMOVE_BLACKLIST_ACCOUNT_SELECTOR: felt252 = selector!("remove_blacklisted(ContractAddress)"); -// // const RECOVER_TOKENS_SELECTOR: felt252 = selector!("recover_tokens(ContractAddress,ContractAddress)"); - - -// } - -// } - diff --git a/cairo/src/helpers/constants.cairo b/cairo/src/helpers/constants.cairo deleted file mode 100644 index 75692b8..0000000 --- a/cairo/src/helpers/constants.cairo +++ /dev/null @@ -1,3 +0,0 @@ -pub const Active: felt252 = 0; -pub const PartialPause: felt252 = 1; -pub const FullPause: felt252 = 2; diff --git a/cairo/src/interfaces/IaccessRegistry.cairo b/cairo/src/interfaces/IaccessRegistry.cairo deleted file mode 100644 index 415d0f4..0000000 --- a/cairo/src/interfaces/IaccessRegistry.cairo +++ /dev/null @@ -1,19 +0,0 @@ -use starknet::ContractAddress; - -pub const IACCESSCONTROL_ID: felt252 = - 0x23700be02858dbe2ac4dc9c9f66d0b6b0ed81ec7f970ca6844500a56ff61751; - -#[starknet::interface] -pub trait IAccessRegistry { - fn is_signer(self: @TContractState, account: ContractAddress) -> bool; - fn get_total_signer(self:@TContractState)->u64; - fn add_signer(ref self: TContractState, new_signer: ContractAddress); - fn remove_signer(ref self: TContractState, existing_owner: ContractAddress); - fn renounce_signership(ref self: TContractState, signer: ContractAddress); - fn accept_super_adminship(ref self: TContractState); - fn get_super_admin(self: @TContractState) -> ContractAddress; - fn pending_super_admin(self: @TContractState) -> ContractAddress; - fn transfer_super_adminship(ref self: TContractState, new_super_admin: ContractAddress); - fn super_admin_ownership_valid_for(self: @TContractState) -> u64; - fn super_handover_expires_at(self: @TContractState) -> u64; -} diff --git a/cairo/src/interfaces/IblackListed.cairo b/cairo/src/interfaces/IblackListed.cairo deleted file mode 100644 index 3f849ac..0000000 --- a/cairo/src/interfaces/IblackListed.cairo +++ /dev/null @@ -1,7 +0,0 @@ -use starknet::ContractAddress; -#[starknet::interface] -pub trait IBlackListedComponent { - fn is_blacklisted_account(self: @TContractState, account: ContractAddress) -> bool; - fn blacklist_account(ref self: TContractState, account: ContractAddress); - fn remove_blacklisted_account(ref self: TContractState, account: ContractAddress); -} diff --git a/cairo/src/interfaces/Ipausable.cairo b/cairo/src/interfaces/Ipausable.cairo deleted file mode 100644 index 3ff3297..0000000 --- a/cairo/src/interfaces/Ipausable.cairo +++ /dev/null @@ -1,25 +0,0 @@ -use cairo::helpers::constants; -// Define the pause states using an enum -#[derive(Drop, Copy, Serde)] -pub enum PauseState { - Active, - PartialPause, - FullPause -} - -#[starknet::interface] -pub trait IPausable { - fn get_current_state(self: @T1) -> PauseState; - fn is_active(self: @T1) -> bool; - fn is_partial_paused(self: @T1) -> bool; - fn is_full_paused(self: @T1) -> bool; -} - -fn get_state_felt(state: PauseState) -> felt252 { - match state { - PauseState::Active => constants::Active, - PauseState::PartialPause => constants::PartialPause, - PauseState::FullPause => constants::FullPause - } -} - diff --git a/cairo/src/interfaces/IsuperAdmin2Step.cairo b/cairo/src/interfaces/IsuperAdmin2Step.cairo deleted file mode 100644 index 750ee23..0000000 --- a/cairo/src/interfaces/IsuperAdmin2Step.cairo +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -use starknet::ContractAddress; - - -#[starknet::interface] -pub trait ISuperAdminTwoStep { - fn super_admin(self: @TState) -> ContractAddress; - fn pending_super_admin(self: @TState) -> ContractAddress; - fn transfer_super_adminship(ref self: TState, new_super_admin: ContractAddress); - fn super_admin_ownership_valid_for(self: @TState) -> u64; - fn super_handover_expires_at(self: @TState) -> u64; -} diff --git a/cairo/src/lib.cairo b/cairo/src/lib.cairo deleted file mode 100644 index 5bc7274..0000000 --- a/cairo/src/lib.cairo +++ /dev/null @@ -1,24 +0,0 @@ - - pub mod components { - pub mod Pausable; - pub mod BlackListed; - - } - -pub mod contracts{ - pub mod AccessControl; - pub mod HSTK; - pub mod MultisigL2; - - } - -pub mod interfaces { - pub mod Ipausable; - pub mod IblackListed; - pub mod IaccessRegistry; -} - pub mod helpers { - pub mod constants; - } - -// pub mod HSTK; diff --git a/solidity/src/AccessRegistry/AccessRegistry.sol b/solidity/src/AccessRegistry/AccessRegistry.sol index 3e5d95c..8ed2dce 100644 --- a/solidity/src/AccessRegistry/AccessRegistry.sol +++ b/solidity/src/AccessRegistry/AccessRegistry.sol @@ -55,49 +55,55 @@ abstract contract AccessRegistry is Context, SuperAdmin2Step, FallbackAdmin2Step signers[_superAdmin] = true; } - function addSigner(address _newSigner) external virtual onlySuperAdmin notZeroAddress(_newSigner) { - // require(!isSigner(_newSigner), "ACL::Already A Signer"); - if (isSigner(_newSigner)) revert AlreadySigner(); - signers[_newSigner] = true; - assembly { - // Emit SignerAdded event - log2( - 0x00, // start of data - 0x00, // length of data (0 as no data needed) - 0x47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f24, // keccak256("SignerAdded(address)") - _newSigner // indexed parameter - ) + function addSigner(address _newSigner) external virtual onlySuperAdmin { + _addSigner(_newSigner); + assembly{ + sstore(_TOTAL_SIGNER_SLOT, add(sload(_TOTAL_SIGNER_SLOT), 1)) + } - sstore(_TOTAL_SIGNER_SLOT, add(sload(_TOTAL_SIGNER_SLOT), 1)) + } + + function addBatchSigners(address[] calldata newSigners) external virtual onlySuperAdmin{ + + uint256 totalSigners = newSigners.length; + + for(uint i=0; i < totalSigners; i++){ + _addSigner(newSigners[i]); + } + assembly { + sstore(_TOTAL_SIGNER_SLOT, add(sload(_TOTAL_SIGNER_SLOT),totalSigners)) } + } - function removeSigner(address _signer) external virtual onlySuperAdmin notZeroAddress(_signer) { - if (!isSigner(_signer)) revert NonExistingSigner(); - if (_signer == superAdmin()) revert SuperAdminCannotRemoved(); - if (totalSigners() == 1) revert WalletCannotBeSignerLess(); - // require(totalSigners() > 1, "ACL::wallet cannot be ownerless"); - signers[_signer] = false; - assembly { - // Emit SignerAdded event - log2( - 0x00, // start of data - 0x00, // length of data (0 as no data needed) - 0x3525e22824a8a7df2c9a6029941c824cf95b6447f1e13d5128fd3826d35afe8b, // keccak256("SignerRemoved(address)") - _signer // indexed parameter - ) - sstore(_TOTAL_SIGNER_SLOT, sub(sload(_TOTAL_SIGNER_SLOT), 1)) + function removeBatchSigners(address[] calldata exisitingSigner) external virtual onlySuperAdmin{ + + uint256 totalSigners = exisitingSigner.length; + + for(uint i=0;i authorization status (true = authorized, false = unauthorized) @@ -86,14 +90,13 @@ modifier onlyAuthorizedBridge() { * @param _bridge Address of the L2 standard bridge. * @param _remoteToken Address of the corresponding L1 token. */ - constructor(address _bridge, address _remoteToken, address _multiSig) + constructor(address _bridge, address _remoteToken, address _admin) ERC20("HSTK", "HSTK") Semver(1, 0, 0) - Pausable() - BlackListed(_multiSig) { REMOTE_TOKEN = _remoteToken; authorizedBridges[_bridge] = true; + admin =_admin; } @@ -102,7 +105,9 @@ modifier onlyAuthorizedBridge() { * @dev Can only be called by contract admin/owner * @param _bridge Address of the bridge to authorize */ -function authorizeBridge(address _bridge) external onlyMultiSig { +function authorizeBridge(address _bridge) external { + + require(_msgSender() == admin,"Caller Needs to be Admin"); require(_bridge != address(0), "OptimismMintableERC20: bridge cannot be zero address"); require(!authorizedBridges[_bridge], "OptimismMintableERC20: bridge already authorized"); @@ -115,7 +120,9 @@ function authorizeBridge(address _bridge) external onlyMultiSig { * @dev Can only be called by contract admin/owner * @param _bridge Address of the bridge to unauthorized */ -function revokeBridgeAuthorization(address _bridge) external onlyMultiSig { +function revokeBridgeAuthorization(address _bridge) external { + + require(_msgSender() == admin,"Caller Needs to be Admin"); require(_bridge != address(0), "OptimismMintableERC20: bridge cannot be zero address"); require(authorizedBridges[_bridge], "OptimismMintableERC20: bridge not authorized"); @@ -123,14 +130,14 @@ function revokeBridgeAuthorization(address _bridge) external onlyMultiSig { emit BridgeUnauthorized(_bridge, _msgSender()); } -/** - * @notice Checks if a given address is an authorized bridge - * @param _bridge Address to check for bridge authorization - * @return bool True if the address is an authorized bridge, false otherwise - */ -function isAuthorizedBridge(address _bridge) public view returns(bool) { - return authorizedBridges[_bridge]; -} + /** + * @notice Checks if a given address is an authorized bridge + * @param _bridge Address to check for bridge authorization + * @return bool True if the address is an authorized bridge, false otherwise + */ + function isAuthorizedBridge(address _bridge) public view returns(bool) { + return authorizedBridges[_bridge]; + } /** * @notice Allows the StandardBridge on this network to mint tokens. @@ -143,8 +150,6 @@ function isAuthorizedBridge(address _bridge) public view returns(bool) { virtual override(IOptimismMintableERC20, ILegacyMintableERC20) onlyAuthorizedBridge - allowedInActiveOrPartialPause - notBlackListed(_to) { _mint(_to, _amount); emit Mint(_to, _amount); @@ -161,74 +166,11 @@ function isAuthorizedBridge(address _bridge) public view returns(bool) { virtual override(IOptimismMintableERC20, ILegacyMintableERC20) onlyAuthorizedBridge - allowedInActiveOrPartialPause { _burn(_from, _amount); emit Burn(_from, _amount); } - /** - * @dev See {ERC20-transfer}. - * Added partialPausedOff and pausedOff modifiers - */ - function transfer(address to, uint256 value) - public - override - whenActive - notBlackListed(_msgSender()) - notBlackListed(to) - returns (bool) - { - return super.transfer(to, value); - } - - /** - * @dev See {ERC20-transferFrom}. - * Added partialPausedOff and pausedOff modifiers - */ - function transferFrom(address from, address to, uint256 value) - public - override - whenActive - notBlackListed(_msgSender()) - notBlackListed(from) - notBlackListed(to) - returns (bool) - { - return super.transferFrom(from, to, value); - } - - /** - * @dev See {ERC20-approve}. - * Added pausedOff modifier - */ - function approve(address spender, uint256 value) - public - override - allowedInActiveOrPartialPause - notBlackListed(_msgSender()) - notBlackListed(spender) - returns (bool) - { - return super.approve(spender, value); - } - - /** - * @dev Recovers tokens accidentally sent to this contract - * @param asset The address of the token to recover - * @param to The address to send the recovered tokens - * Requirements: - * - Can only be called by the admin - * - `asset` and `to` cannot be the zero address - * @notice This function can be used to recover any ERC20 tokens sent to this contract by mistake - */ - function recoverToken(address asset, address to) external allowedInActiveOrPartialPause onlyMultiSig { - IERC20 interfaceAsset = IERC20(asset); - uint256 balance = interfaceAsset.balanceOf(address(this)); - interfaceAsset.safeTransfer(to, balance); - emit Token_Rescued(asset, to, balance); - } - /** * @notice ERC165 interface check function. * @@ -245,16 +187,6 @@ function isAuthorizedBridge(address _bridge) public view returns(bool) { return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3; } - /** - * @dev Updates the contract's operational state - * @param newState The new state to set (0: Active, 1: Partial Pause, 2: Full Pause) - * Requirements: - * - Can only be called by the MultiSig - */ - function updateOperationalState(uint8 newState) external onlyMultiSig { - _updateOperationalState(newState); - } - /** * @custom:legacy * @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward. diff --git a/solidity/test/MultiSig.t.sol b/solidity/test/MultiSig.t.sol index 371e1b8..a82fa69 100644 --- a/solidity/test/MultiSig.t.sol +++ b/solidity/test/MultiSig.t.sol @@ -18,6 +18,9 @@ contract MultiSigContractTest is Test { Expired, Executed } + bytes4[] selectors; + bytes[] params; + address [] signers; MultiSigWallet public multiSigImplementation; ERC1967Proxy public multiSig; @@ -31,6 +34,24 @@ contract MultiSigContractTest is Test { address public fallbackAdmin = makeAddr("fallbackAdmin"); address public nonSigner = makeAddr("nonSigner"); + ///@dev bytes4(keccak256("mint(address,uint256)")) + bytes4 public constant MINT_SELECTOR = 0x40c10f19; + + ///@dev bytes4(keccak256("burn(address,uint256)")) + bytes4 public constant BURN_SELECTOR = 0x9dc29fac; + + ///@dev bytes4(keccak256("updateOperationalState(uint8)")) + bytes4 public constant PAUSE_STATE_SELECTOR = 0x50f20190; + + ///@dev bytes4(keccak256("blackListAccount(address)")) + bytes4 public constant BLACKLIST_ACCOUNT_SELECTOR = 0xe0644962; + + ///@dev bytes4(keccak256("removeBlackListedAccount(address)")) + bytes4 public constant REMOVE_BLACKLIST_ACCOUNT_SELECTOR = 0xc460f1be; + + ///@dev bytes4(keccak256("recoverToken(address,address)")) + bytes4 public constant RECOVER_TOKENS_SELECTOR = 0xfeaea586; + event SignerAdded(address indexed signer); event SignerRemoved(address indexed signer); event SignerRenounced(address indexed from, address indexed to); @@ -80,19 +101,19 @@ contract MultiSigContractTest is Test { function test_AddSigner() public { vm.startPrank(superAdmin); - vm.expectEmit(true, false, false, false); emit SignerAdded(signer3); - wrappedMultiSig.addSigner(signer3); wrappedMultiSig.addSigner(signer2); wrappedMultiSig.addSigner(signer1); - unchecked { - assertTrue(wrappedMultiSig.isSigner(signer3)); - assertTrue(!wrappedMultiSig.isSigner(nonSigner)); - assertEq(wrappedMultiSig.totalSigners(), 4); - } - + vm.stopPrank(); + } + function test_AddSignerBatch() public { + vm.startPrank(superAdmin); + vm.expectEmit(true, false, false, false); + emit SignerAdded(signer3); + signers = [signer3,signer2,signer1]; + wrappedMultiSig.addBatchSigners(signers); vm.stopPrank(); } @@ -607,6 +628,44 @@ contract MultiSigContractTest is Test { token.transfer(account, 10 * 10 ** 18); assertEq(token.balanceOf(account), 10 * 10 ** 18, "Token Doesn't mint successfully"); } + + + function test_CreateTransactionBatch() public { + address to = address(1223); + //(gas: 4 28 625) + selectors = [MINT_SELECTOR,BURN_SELECTOR,MINT_SELECTOR,BURN_SELECTOR]; + // selectors = [MINT_SELECTOR]; + + params = [ abi.encode(to,10_000) , abi.encode(to,10_000) , abi.encode(to,100_000) , abi.encode(to,100_000)]; + // params = [abi.encode(to,10000)]; + + vm.prank(fallbackAdmin); + wrappedMultiSig.createBatchTransaction(selectors,params); + + } + function test_CreateTransaction() public { + address to = address(1223); + + // (gas: 3 99 118) + //188159 + //1029953 + + vm.prank(fallbackAdmin); + wrappedMultiSig.createMintTransaction(to,10000); + + vm.prank(fallbackAdmin); + wrappedMultiSig.createBurnTransaction(to,100); + + vm.prank(fallbackAdmin); + wrappedMultiSig.createMintTransaction(to,10); + + vm.prank(fallbackAdmin); + wrappedMultiSig.createMintTransaction(to,100000); + + } + + + } //for signers[] array diff --git a/solidity/src/OptimisticStack/MultiSigL2.sol b/solidity/test/mock/MultiSigWallet.sol similarity index 74% rename from solidity/src/OptimisticStack/MultiSigL2.sol rename to solidity/test/mock/MultiSigWallet.sol index e1a892a..1b524f3 100644 --- a/solidity/src/OptimisticStack/MultiSigL2.sol +++ b/solidity/test/mock/MultiSigWallet.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.4; -import {AccessRegistry} from "../AccessRegistry/AccessRegistry.sol"; -import {UUPSUpgradeable} from "../utils/UUPSUpgradeable.sol"; -import {Initializable} from "../utils/Initializable.sol"; +import {AccessRegistry} from "../../src/AccessRegistry/AccessRegistry.sol"; +import {UUPSUpgradeable} from "../../src/utils/UUPSUpgradeable.sol"; +import {Initializable} from "../../src/utils/Initializable.sol"; /** * @title MultisigWallet @@ -19,33 +19,33 @@ contract MultiSigWallet is Initializable, AccessRegistry, UUPSUpgradeable { uint256 private constant APPROVAL_THRESHOLD = 60; // 60% of signers must approve ///@dev bytes4(keccak256("mint(address,uint256)")) - bytes4 private constant MINT_SELECTOR = 0x40c10f19; + bytes4 public constant MINT_SELECTOR = 0x40c10f19; ///@dev bytes4(keccak256("burn(address,uint256)")) - bytes4 private constant BURN_SELECTOR = 0x9dc29fac; + bytes4 public constant BURN_SELECTOR = 0x9dc29fac; ///@dev bytes4(keccak256("updateOperationalState(uint8)")) - bytes4 private constant PAUSE_STATE_SELECTOR = 0x50f20190; + bytes4 public constant PAUSE_STATE_SELECTOR = 0x50f20190; ///@dev bytes4(keccak256("blackListAccount(address)")) - bytes4 private constant BLACKLIST_ACCOUNT_SELECTOR = 0xe0644962; + bytes4 public constant BLACKLIST_ACCOUNT_SELECTOR = 0xe0644962; ///@dev bytes4(keccak256("removeBlackListedAccount(address)")) - bytes4 private constant REMOVE_BLACKLIST_ACCOUNT_SELECTOR = 0xc460f1be; + bytes4 public constant REMOVE_BLACKLIST_ACCOUNT_SELECTOR = 0xc460f1be; ///@dev bytes4(keccak256("recoverToken(address,address)")) - bytes4 private constant RECOVER_TOKENS_SELECTOR = 0xfeaea586; + bytes4 public constant RECOVER_TOKENS_SELECTOR = 0xfeaea586; ///@dev keccak256("HASH.token.hashstack.slot") - bytes32 private constant TOKEN_CONTRACT_SLOT = 0x2e621e7466541a75ed3060ecb302663cf45f24d90bdac97ddad9918834bc5d75; + bytes32 public constant TOKEN_CONTRACT_SLOT = 0x2e621e7466541a75ed3060ecb302663cf45f24d90bdac97ddad9918834bc5d75; // ========== ENUMS ========== enum TransactionState { - Pending, // Just created, awaiting first signature - Active, // Has at least one signature, within time window - Queued, // Has enough signatures, ready for execution - Expired, // Time window passed without enough signatures - Executed // Successfully executed + Pending, // Just created, awaiting first signature + Active, // Has at least one signature, within time window + Queued, // Has enough signatures, ready for execution + Expired, // Time window passed without enough signatures + Executed // Successfully executed } @@ -172,96 +172,22 @@ contract MultiSigWallet is Initializable, AccessRegistry, UUPSUpgradeable { return newState; } - /** - * @notice Creates a standard transaction or calls it if sender is superAdmin - * @param _selector The function selector for the transaction - * @param _params The parameters to pass with the transaction - * @return The timestamp of the transaction - */ - function _createStandardTransaction(bytes4 _selector, bytes memory _params) private returns (uint256) { - if (_msgSender() == superAdmin()) { - emit TransactionProposedBySuperAdmin(block.timestamp); - _call(_selector, _params); - return 10; - } - return createTransaction(_selector, _params); - } - - /** - * @notice Creates a mint transaction - * @param to The address to mint tokens to - * @param amount The amount of tokens to mint - * @return The transaction ID - */ - function createMintTransaction(address to, uint256 amount) external virtual notZeroAddress(to) returns (uint256) { - return _createStandardTransaction(MINT_SELECTOR, abi.encode(to, amount)); - } - - /** - * @notice Creates a burn transaction - * @param from The address from which to burn tokens - * @param amount The amount of tokens to burn - * @return The transaction ID - */ - function createBurnTransaction(address from, uint256 amount) - external - virtual - notZeroAddress(from) - returns (uint256) - { - return _createStandardTransaction(BURN_SELECTOR, abi.encode(from, amount)); - } - - /** - * @notice Creates a transaction to blacklist an account - * @param account The account to blacklist - * @return The transaction ID - */ - function createBlacklistAccountTransaction(address account) - external - virtual - notZeroAddress(account) - returns (uint256) - { - return _createStandardTransaction(BLACKLIST_ACCOUNT_SELECTOR, abi.encode(account)); - } - - /** - * @notice Creates a transaction to remove an account from the blacklist - * @param account The account to remove from the blacklist - * @return The transaction ID - */ - function createBlacklistRemoveTransaction(address account) - external - virtual - notZeroAddress(account) - returns (uint256) - { - return _createStandardTransaction(REMOVE_BLACKLIST_ACCOUNT_SELECTOR, abi.encode(account)); - } + function createBatchTransaction(bytes4[] calldata _selector,bytes[] calldata _params) external returns(uint256[] memory txId){ - /** - * @notice Creates a transaction to change the Pause State of Token - * @return The transaction ID - */ - function createPauseStateTransaction(uint8 _state) external virtual returns (uint256) { - return _createStandardTransaction(PAUSE_STATE_SELECTOR, abi.encode(_state)); - } + if(_selector.length!=_params.length) revert(); + uint size = _selector.length; - /** - * @notice Creates a transaction to recover tokens - * @param token The token address - * @param to The address to send the recovered tokens - * @return The transaction ID - */ - function createRecoverTokensTransaction(address token, address to) - external - virtual - notZeroAddress(token) - notZeroAddress(to) - returns (uint256) - { - return _createStandardTransaction(RECOVER_TOKENS_SELECTOR, abi.encode(token, to)); + if(_msgSender() == superAdmin()){ + for(uint i =0; i< size ;i++){ + emit TransactionProposedBySuperAdmin(block.timestamp); + _call(_selector[i],_params[i]); + } + } + else{ + for(uint i =0;i Date: Wed, 20 Nov 2024 16:44:55 +0530 Subject: [PATCH 8/8] [REFAC] refact multisig code[DONE] --- .../src/AccessRegistry/AccessRegistry.sol | 54 +-- solidity/src/MultiSigWallet.sol | 352 +++++++----------- .../IOptimismMintableERC20.sol | 1 - .../OptimisticStack/OptimismMintableERC20.sol | 91 +++-- solidity/test/MultiSig.t.sol | 311 +++++++++------- solidity/test/mock/MultiSigWallet.sol | 47 ++- 6 files changed, 396 insertions(+), 460 deletions(-) diff --git a/solidity/src/AccessRegistry/AccessRegistry.sol b/solidity/src/AccessRegistry/AccessRegistry.sol index 8ed2dce..cf4199e 100644 --- a/solidity/src/AccessRegistry/AccessRegistry.sol +++ b/solidity/src/AccessRegistry/AccessRegistry.sol @@ -57,50 +57,41 @@ abstract contract AccessRegistry is Context, SuperAdmin2Step, FallbackAdmin2Step function addSigner(address _newSigner) external virtual onlySuperAdmin { _addSigner(_newSigner); - assembly{ - sstore(_TOTAL_SIGNER_SLOT, add(sload(_TOTAL_SIGNER_SLOT), 1)) + assembly { + sstore(_TOTAL_SIGNER_SLOT, add(sload(_TOTAL_SIGNER_SLOT), 1)) } - } - function addBatchSigners(address[] calldata newSigners) external virtual onlySuperAdmin{ - - uint256 totalSigners = newSigners.length; - - for(uint i=0; i < totalSigners; i++){ - _addSigner(newSigners[i]); + function addBatchSigners(address[] calldata newSigners) external virtual onlySuperAdmin { + uint256 totalSigners = newSigners.length; + + for (uint256 i = 0; i < totalSigners; i++) { + _addSigner(newSigners[i]); } - assembly { - sstore(_TOTAL_SIGNER_SLOT, add(sload(_TOTAL_SIGNER_SLOT),totalSigners)) + assembly { + sstore(_TOTAL_SIGNER_SLOT, add(sload(_TOTAL_SIGNER_SLOT), totalSigners)) } - } + function removeBatchSigners(address[] calldata exisitingSigner) external virtual onlySuperAdmin { + uint256 totalSigners = exisitingSigner.length; - function removeBatchSigners(address[] calldata exisitingSigner) external virtual onlySuperAdmin{ - - uint256 totalSigners = exisitingSigner.length; - - for(uint i=0;i 0 && amount < 9_000_000_000 * 10 ** 18 - 10 ** 18); + + selectors = [MINT_SELECTOR]; + params = [abi.encode(to,amount)]; vm.prank(fallbackAdmin); - uint256 trnx = wrappedMultiSig.createMintTransaction(to, amount); + txId = wrappedMultiSig.createBatchTransaction(selectors, params); - (,,,,,, MultiSigWallet.TransactionState state,) = wrappedMultiSig.getTransaction(trnx); + (,,,,,, MultiSigWallet.TransactionState state,) = wrappedMultiSig.getTransaction(txId[0]); assertEq(uint8(state), 0, "Transaction need to be in Pending State"); // vm.warp(block.timestamp + 72 hours - 1); @@ -493,15 +526,15 @@ contract MultiSigContractTest is Test { // assertEq(uint8(state),1,"Transaction need to be in Active State"); vm.prank(signer1); - wrappedMultiSig.approveTransaction(trnx); - (,,,,,, state,) = wrappedMultiSig.getTransaction(trnx); + wrappedMultiSig.approveBatchTransaction(txId); + (,,,,,, state,) = wrappedMultiSig.getTransaction(txId[0]); assertEq(uint8(state), 1, "Transaction need to be in Active State"); vm.warp(block.timestamp + 24 hours + 1); vm.expectRevert(); vm.prank(signer1); - wrappedMultiSig.revokeConfirmation(trnx); - MultiSigWallet.TransactionState state_ = wrappedMultiSig.updateTransactionState(trnx); + wrappedMultiSig.revokeBatchConfirmation(txId); + MultiSigWallet.TransactionState state_ = wrappedMultiSig.updateTransactionState(txId[0]); assertEq(uint8(state_), 3, "Transaction should be expired"); } @@ -571,24 +604,27 @@ contract MultiSigContractTest is Test { address account = makeAddr("account"); address to = makeAddr("to"); test_FallbackAdminMintTransaction(); + + selectors = [BLACKLIST_ACCOUNT_SELECTOR]; + params = [abi.encode(account)]; vm.prank(signer1); - uint256 txId = wrappedMultiSig.createBlacklistAccountTransaction(account); + txId = wrappedMultiSig.createBatchTransaction(selectors,params); vm.prank(signer1); - wrappedMultiSig.approveTransaction(txId); + wrappedMultiSig.approveBatchTransaction(txId); vm.prank(signer2); - wrappedMultiSig.approveTransaction(txId); + wrappedMultiSig.approveBatchTransaction(txId); vm.prank(signer3); - wrappedMultiSig.approveTransaction(txId); + wrappedMultiSig.approveBatchTransaction(txId); vm.prank(superAdmin); - wrappedMultiSig.approveTransaction(txId); + wrappedMultiSig.approveBatchTransaction(txId); vm.prank(address(3)); vm.warp(block.timestamp + 24 hours + 1); - wrappedMultiSig.executeTransaction(txId); + wrappedMultiSig.executeBatchTransaction(txId); assertEq(token.isBlackListed(account), true, "Inconsistent State"); @@ -603,24 +639,27 @@ contract MultiSigContractTest is Test { address account = makeAddr("account"); address to = makeAddr("to"); + selectors = [REMOVE_BLACKLIST_ACCOUNT_SELECTOR]; + params = [abi.encode(account)]; + vm.prank(signer1); - uint256 txId = wrappedMultiSig.createBlacklistRemoveTransaction(account); + txId = wrappedMultiSig.createBatchTransaction(selectors,params); vm.prank(signer1); - wrappedMultiSig.approveTransaction(txId); + wrappedMultiSig.approveBatchTransaction(txId); vm.prank(signer2); - wrappedMultiSig.approveTransaction(txId); + wrappedMultiSig.approveBatchTransaction(txId); vm.prank(signer3); - wrappedMultiSig.approveTransaction(txId); + wrappedMultiSig.approveBatchTransaction(txId); vm.prank(superAdmin); - wrappedMultiSig.approveTransaction(txId); + wrappedMultiSig.approveBatchTransaction(txId); vm.prank(address(3)); vm.warp(block.timestamp + 24 hours + 1); - wrappedMultiSig.executeTransaction(txId); + wrappedMultiSig.executeBatchTransaction(txId); assertEq(token.isBlackListed(account), false, "Inconsistent State"); @@ -629,43 +668,41 @@ contract MultiSigContractTest is Test { assertEq(token.balanceOf(account), 10 * 10 ** 18, "Token Doesn't mint successfully"); } - function test_CreateTransactionBatch() public { address to = address(1223); //(gas: 4 28 625) - selectors = [MINT_SELECTOR,BURN_SELECTOR,MINT_SELECTOR,BURN_SELECTOR]; + selectors = [MINT_SELECTOR, BURN_SELECTOR, MINT_SELECTOR, BURN_SELECTOR]; // selectors = [MINT_SELECTOR]; - - params = [ abi.encode(to,10_000) , abi.encode(to,10_000) , abi.encode(to,100_000) , abi.encode(to,100_000)]; - // params = [abi.encode(to,10000)]; - - vm.prank(fallbackAdmin); - wrappedMultiSig.createBatchTransaction(selectors,params); - } - function test_CreateTransaction() public { - address to = address(1223); + params = [abi.encode(to, 10_000), abi.encode(to, 10_000), abi.encode(to, 100_000), abi.encode(to, 100_000)]; - // (gas: 3 99 118) - //188159 - //1029953 - - vm.prank(fallbackAdmin); - wrappedMultiSig.createMintTransaction(to,10000); + uint256 gasBefore = gasleft(); + vm.prank(superAdmin); + wrappedMultiSig.createBatchTransaction(selectors, params); - vm.prank(fallbackAdmin); - wrappedMultiSig.createBurnTransaction(to,100); + uint256 gasAfter = gasleft(); - vm.prank(fallbackAdmin); - wrappedMultiSig.createMintTransaction(to,10); + console.log("Gas used", gasBefore - gasAfter); + } - vm.prank(fallbackAdmin); - wrappedMultiSig.createMintTransaction(to,100000); + // function test_CreateTransaction() public { + // address to = address(1223); - } + // // (gas: 3 99 118) + // //188159 + // //1029953 + // uint256 gasBefore = gasleft(); + // vm.prank(superAdmin); + // wrappedMultiSig.createMintTransaction(to, 10_000); + // uint256 gasAfter = gasleft(); + // console.log("gas USed : ", gasBefore - gasAfter); + // } + + // function test_approveTransaction() public { + // } } //for signers[] array diff --git a/solidity/test/mock/MultiSigWallet.sol b/solidity/test/mock/MultiSigWallet.sol index 1b524f3..b88bc2c 100644 --- a/solidity/test/mock/MultiSigWallet.sol +++ b/solidity/test/mock/MultiSigWallet.sol @@ -41,11 +41,11 @@ contract MultiSigWallet is Initializable, AccessRegistry, UUPSUpgradeable { // ========== ENUMS ========== enum TransactionState { - Pending, // Just created, awaiting first signature - Active, // Has at least one signature, within time window - Queued, // Has enough signatures, ready for execution - Expired, // Time window passed without enough signatures - Executed // Successfully executed + Pending, // Just created, awaiting first signature + Active, // Has at least one signature, within time window + Queued, // Has enough signatures, ready for execution + Expired, // Time window passed without enough signatures + Executed // Successfully executed } @@ -172,20 +172,21 @@ contract MultiSigWallet is Initializable, AccessRegistry, UUPSUpgradeable { return newState; } - function createBatchTransaction(bytes4[] calldata _selector,bytes[] calldata _params) external returns(uint256[] memory txId){ - - if(_selector.length!=_params.length) revert(); - uint size = _selector.length; + function createBatchTransaction(bytes4[] calldata _selector, bytes[] calldata _params) + external + returns (uint256[] memory txId) + { + if (_selector.length != _params.length) revert(); + uint256 size = _selector.length; - if(_msgSender() == superAdmin()){ - for(uint i =0; i< size ;i++){ - emit TransactionProposedBySuperAdmin(block.timestamp); - _call(_selector[i],_params[i]); - } - } - else{ - for(uint i =0;i