From 54b2f219fc889aca5e2029b9fbe12a0d18cc921f Mon Sep 17 00:00:00 2001 From: JChoy Date: Wed, 7 Aug 2024 17:59:49 +0900 Subject: [PATCH] refactor: hook_caller component => hooks_caller library --- src/book_manager.cairo | 47 +++--- src/components/hook_caller.cairo | 243 ------------------------------ src/interfaces/book_manager.cairo | 2 + src/lib.cairo | 3 +- src/libraries/hooks.cairo | 2 +- src/libraries/hooks_caller.cairo | 202 +++++++++++++++++++++++++ 6 files changed, 232 insertions(+), 267 deletions(-) delete mode 100644 src/components/hook_caller.cairo create mode 100644 src/libraries/hooks_caller.cairo diff --git a/src/book_manager.cairo b/src/book_manager.cairo index e99efe4..ac8dc8d 100644 --- a/src/book_manager.cairo +++ b/src/book_manager.cairo @@ -10,7 +10,6 @@ pub mod BookManager { use clober_cairo::interfaces::book_manager::IBookManager; use clober_cairo::interfaces::locker::{ILockerDispatcher, ILockerDispatcherTrait}; use clober_cairo::interfaces::params::{MakeParams, TakeParams, CancelParams, OrderInfo}; - use clober_cairo::components::hook_caller::HookCallerComponent; use clober_cairo::components::lockers::LockersComponent; use clober_cairo::libraries::i257::{i257, I257Trait}; use clober_cairo::libraries::book_key::{BookKey, BookKeyTrait}; @@ -19,8 +18,8 @@ pub mod BookManager { use clober_cairo::libraries::order_id::{OrderId, OrderIdTrait}; use clober_cairo::libraries::tick::{Tick, TickTrait}; use clober_cairo::libraries::hooks::{Hooks, HooksTrait}; + use clober_cairo::libraries::hooks_caller::{HooksCaller, HooksCallerTrait}; - component!(path: HookCallerComponent, storage: hook_caller, event: HookCallerEvent); component!(path: LockersComponent, storage: lockers, event: LockersEvent); component!(path: ERC721Component, storage: erc721, event: ERC721Event); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -48,10 +47,6 @@ pub mod BookManager { #[abi(embed_v0)] impl SRC5Impl = SRC5Component::SRC5Impl; - #[abi(embed_v0)] - impl HookCallerImpl = HookCallerComponent::HookCallerImpl; - impl HookCallerInternalImpl = HookCallerComponent::InternalImpl; - #[abi(embed_v0)] impl LockersImpl = LockersComponent::LockersImpl; impl LockersInternalImpl = LockersComponent::InternalImpl; @@ -65,9 +60,8 @@ pub mod BookManager { #[substorage(v0)] src5: SRC5Component::Storage, #[substorage(v0)] - hook_caller: HookCallerComponent::Storage, - #[substorage(v0)] lockers: LockersComponent::Storage, + hooks_caller: HooksCaller, currency_delta: Map<(ContractAddress, ContractAddress), i257>, contract_uri: ByteArray, default_provier: ContractAddress, @@ -87,8 +81,6 @@ pub mod BookManager { #[flat] SRC5Event: SRC5Component::Event, #[flat] - HookCallerEvent: HookCallerComponent::Event, - #[flat] LockersEvent: LockersComponent::Event, Open: Open, Make: Make, @@ -210,7 +202,7 @@ pub mod BookManager { fn _check_locker(self: @ContractState) { let caller = get_caller_address(); let locker = self.lockers.get_current_locker(); - let hook = self.hook_caller.get_current_hook(); + let hook = self.hooks_caller.read().get_current_hook(); assert(caller == locker || caller == hook, Errors::INVALID_LOCKER); } @@ -276,6 +268,14 @@ pub mod BookManager { self.token_owed.read((owner, currency)) } + fn get_current_hook(self: @ContractState) -> ContractAddress { + self.hooks_caller.read().get_current_hook() + } + + fn get_hook(self: @ContractState, i: u32) -> ContractAddress { + self.hooks_caller.read().get_hook(i) + } + fn get_book_key(self: @ContractState, book_id: felt252) -> BookKey { self.books.read(book_id).key } @@ -342,7 +342,8 @@ pub mod BookManager { assert(key.hooks.is_valid_hook_address(), Errors::INVALID_HOOKS); - self.hook_caller.before_open(@key.hooks, @key, hook_data); + let mut hooks_caller = self.hooks_caller.read(); + hooks_caller.before_open(@key.hooks, @key, hook_data); let book_id = key.to_id(); let mut book = self.books.read(book_id); @@ -361,7 +362,7 @@ pub mod BookManager { } ); - self.hook_caller.after_open(@key.hooks, @key, hook_data); + hooks_caller.after_open(@key.hooks, @key, hook_data); } fn lock( @@ -400,7 +401,8 @@ pub mod BookManager { let mut book = self.books.read(book_id); book.check_opened(); - self.hook_caller.before_make(@params.key.hooks, @params, hook_data); + let mut hooks_caller = self.hooks_caller.read(); + hooks_caller.before_make(@params.key.hooks, @params, hook_data); let order_index = book.make(params.tick, params.unit, params.provider); let order_id = (OrderId { book_id, tick: params.tick, index: order_index }).encode(); @@ -427,7 +429,7 @@ pub mod BookManager { } ); - self.hook_caller.after_make(@params.key.hooks, @params, order_id, hook_data); + hooks_caller.after_make(@params.key.hooks, @params, order_id, hook_data); (order_id, quote_amount) } @@ -442,7 +444,8 @@ pub mod BookManager { let mut book = self.books.read(book_id); book.check_opened(); - self.hook_caller.before_take(@params.key.hooks, @params, hook_data); + let mut hooks_caller = self.hooks_caller.read(); + hooks_caller.before_take(@params.key.hooks, @params, hook_data); let taken_unit = book.take(params.tick, params.max_unit); let mut quote_amount: u256 = taken_unit.into() * params.key.unit_size.into(); @@ -470,7 +473,7 @@ pub mod BookManager { } ); - self.hook_caller.after_take(@params.key.hooks, @params, taken_unit, hook_data); + hooks_caller.after_take(@params.key.hooks, @params, taken_unit, hook_data); (quote_amount, base_amount) } @@ -485,7 +488,8 @@ pub mod BookManager { let mut book = self.books.read(params.id); let key = book.key; - self.hook_caller.before_cancel(@key.hooks, @params, hook_data); + let mut hooks_caller = self.hooks_caller.read(); + hooks_caller.before_cancel(@key.hooks, @params, hook_data); let decoded_order_id = OrderIdTrait::decode(params.id); let (canceled_unit, pending_unit) = book.cancel(decoded_order_id, params.to_unit); @@ -504,7 +508,7 @@ pub mod BookManager { self.emit(Cancel { order_id: params.id, unit: canceled_unit }); - self.hook_caller.after_cancel(@key.hooks, @params, canceled_unit, hook_data); + hooks_caller.after_cancel(@key.hooks, @params, canceled_unit, hook_data); canceled_amount } @@ -521,7 +525,8 @@ pub mod BookManager { let mut book = self.books.read(decoded_order_id.book_id); let key = book.key; - self.hook_caller.before_claim(@key.hooks, id, hook_data); + let mut hooks_caller = self.hooks_caller.read(); + hooks_caller.before_claim(@key.hooks, id, hook_data); let claimed_unit = book.claim(decoded_order_id.tick, decoded_order_id.index); @@ -573,7 +578,7 @@ pub mod BookManager { self.emit(Claim { order_id: id, unit: claimed_unit }); - self.hook_caller.after_claim(@key.hooks, id, claimed_unit, hook_data); + hooks_caller.after_claim(@key.hooks, id, claimed_unit, hook_data); claimed_amount } diff --git a/src/components/hook_caller.cairo b/src/components/hook_caller.cairo deleted file mode 100644 index a67278f..0000000 --- a/src/components/hook_caller.cairo +++ /dev/null @@ -1,243 +0,0 @@ -#[starknet::component] -pub mod HookCallerComponent { - use clober_cairo::interfaces::hook_caller::IHookCaller; - use clober_cairo::utils::constants::ZERO_ADDRESS; - use clober_cairo::libraries::hooks::{Hooks, HooksTrait, Permission}; - use clober_cairo::libraries::book_key::BookKey; - use clober_cairo::interfaces::params::{MakeParams, TakeParams, CancelParams}; - use core::starknet::storage::StoragePointerWriteAccess; - use starknet::{SyscallResultTrait, ContractAddress, syscalls, get_caller_address}; - use starknet::storage::Map; - - #[storage] - struct Storage { - hooks: Map, - length: u128, - } - - #[embeddable_as(HookCallerImpl)] - pub impl HookCaller< - TContractState, +HasComponent - > of IHookCaller> { - fn get_current_hook(self: @ComponentState) -> ContractAddress { - let length = self.length.read(); - if length == 0 { - ZERO_ADDRESS() - } else { - self.hooks.read(length - 1) - } - } - - fn get_hook(self: @ComponentState, i: u128) -> ContractAddress { - self.hooks.read(i) - } - } - - #[generate_trait] - pub impl InternalImpl< - TContractState, +HasComponent - > of InternalTrait { - fn call_hook( - ref self: ComponentState, - hooks: @Hooks, - expected_selector: felt252, - hook_data: Span - ) { - // @dev Set current hook here - let length = self.length.read(); - self.hooks.write(length, *hooks.address); - self.length.write(length + 1); - - let mut res = syscalls::call_contract_syscall( - *hooks.address, expected_selector, hook_data - ) - .unwrap_syscall(); - - let selector = Serde::::deserialize(ref res).unwrap(); - - // @dev Clear current hook here - self.hooks.write(length, ZERO_ADDRESS()); - self.length.write(length); - - assert(selector == expected_selector, 'InvalidHookResponse'); - } - - fn before_open( - ref self: ComponentState, - hooks: @Hooks, - key: @BookKey, - hook_data: Span - ) { - if (hooks.has_permission(Permission::BEFORE_OPEN)) { - let caller = get_caller_address(); - let mut data: Array = ArrayTrait::new(); - Serde::serialize(@caller, ref data); - Serde::serialize(key, ref data); - Serde::serialize(@hook_data, ref data); - - self.call_hook(hooks, selector!("before_open"), data.span()); - } - } - - fn after_open( - ref self: ComponentState, - hooks: @Hooks, - key: @BookKey, - hook_data: Span - ) { - if (hooks.has_permission(Permission::AFTER_OPEN)) { - let caller = get_caller_address(); - let mut data: Array = ArrayTrait::new(); - Serde::serialize(@caller, ref data); - Serde::serialize(key, ref data); - Serde::serialize(@hook_data, ref data); - - self.call_hook(hooks, selector!("after_open"), data.span()); - } - } - - fn before_make( - ref self: ComponentState, - hooks: @Hooks, - params: @MakeParams, - hook_data: Span - ) { - if (hooks.has_permission(Permission::BEFORE_MAKE)) { - let caller = get_caller_address(); - let mut data: Array = ArrayTrait::new(); - Serde::serialize(@caller, ref data); - Serde::serialize(params, ref data); - Serde::serialize(@data, ref data); - - self.call_hook(hooks, selector!("before_make"), data.span()); - } - } - - fn after_make( - ref self: ComponentState, - hooks: @Hooks, - params: @MakeParams, - order_id: felt252, - hook_data: Span - ) { - if (hooks.has_permission(Permission::AFTER_MAKE)) { - let caller = get_caller_address(); - let mut data: Array = ArrayTrait::new(); - Serde::serialize(@caller, ref data); - Serde::serialize(params, ref data); - Serde::serialize(@order_id, ref data); - Serde::serialize(@data, ref data); - - self.call_hook(hooks, selector!("after_make"), data.span()); - } - } - - fn before_take( - ref self: ComponentState, - hooks: @Hooks, - params: @TakeParams, - hook_data: Span - ) { - if (hooks.has_permission(Permission::BEFORE_TAKE)) { - let caller = get_caller_address(); - let mut data: Array = ArrayTrait::new(); - Serde::serialize(@caller, ref data); - Serde::serialize(params, ref data); - Serde::serialize(@data, ref data); - - self.call_hook(hooks, selector!("before_take"), data.span()); - } - } - - fn after_take( - ref self: ComponentState, - hooks: @Hooks, - params: @TakeParams, - taken_unit: u64, - hook_data: Span - ) { - if (hooks.has_permission(Permission::AFTER_TAKE)) { - let caller = get_caller_address(); - let mut data: Array = ArrayTrait::new(); - Serde::serialize(@caller, ref data); - Serde::serialize(params, ref data); - Serde::serialize(@taken_unit, ref data); - Serde::serialize(@data, ref data); - - self.call_hook(hooks, selector!("after_take"), data.span()); - } - } - - fn before_cancel( - ref self: ComponentState, - hooks: @Hooks, - params: @CancelParams, - hook_data: Span - ) { - if (hooks.has_permission(Permission::BEFORE_CANCEL)) { - let caller = get_caller_address(); - let mut data: Array = ArrayTrait::new(); - Serde::serialize(@caller, ref data); - Serde::serialize(params, ref data); - Serde::serialize(@data, ref data); - - self.call_hook(hooks, selector!("before_cancel"), data.span()); - } - } - - fn after_cancel( - ref self: ComponentState, - hooks: @Hooks, - params: @CancelParams, - canceled_unit: u64, - hook_data: Span - ) { - if (hooks.has_permission(Permission::AFTER_CANCEL)) { - let caller = get_caller_address(); - let mut data: Array = ArrayTrait::new(); - Serde::serialize(@caller, ref data); - Serde::serialize(params, ref data); - Serde::serialize(@canceled_unit, ref data); - Serde::serialize(@data, ref data); - - self.call_hook(hooks, selector!("after_cancel"), data.span()); - } - } - - fn before_claim( - ref self: ComponentState, - hooks: @Hooks, - order_id: felt252, - hook_data: Span - ) { - if (hooks.has_permission(Permission::BEFORE_CLAIM)) { - let caller = get_caller_address(); - let mut data: Array = ArrayTrait::new(); - Serde::serialize(@caller, ref data); - Serde::serialize(@order_id, ref data); - Serde::serialize(@data, ref data); - - self.call_hook(hooks, selector!("before_claim"), data.span()); - } - } - - fn after_claim( - ref self: ComponentState, - hooks: @Hooks, - order_id: felt252, - claimed_unit: u64, - hook_data: Span - ) { - if (hooks.has_permission(Permission::AFTER_CLAIM)) { - let caller = get_caller_address(); - let mut data: Array = ArrayTrait::new(); - Serde::serialize(@caller, ref data); - Serde::serialize(@order_id, ref data); - Serde::serialize(@claimed_unit, ref data); - Serde::serialize(@data, ref data); - - self.call_hook(hooks, selector!("after_claim"), data.span()); - } - } - } -} diff --git a/src/interfaces/book_manager.cairo b/src/interfaces/book_manager.cairo index 9966cd4..55f1a0b 100644 --- a/src/interfaces/book_manager.cairo +++ b/src/interfaces/book_manager.cairo @@ -17,6 +17,8 @@ pub trait IBookManager { fn token_owed( self: @TContractState, owner: ContractAddress, currency: ContractAddress, token_id: felt252 ) -> u256; + fn get_current_hook(self: @TContractState) -> ContractAddress; + fn get_hook(self: @TContractState, i: u32) -> ContractAddress; fn get_book_key(self: @TContractState, book_id: felt252) -> BookKey; fn get_currency_delta( self: @TContractState, locker: ContractAddress, currency: ContractAddress, diff --git a/src/lib.cairo b/src/lib.cairo index b7b0116..913a7d1 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -1,11 +1,9 @@ pub mod components { - pub mod hook_caller; pub mod lockers; } pub mod interfaces { pub mod book_manager; - pub mod hook_caller; pub mod locker; pub mod lockers; pub mod params; @@ -16,6 +14,7 @@ pub mod libraries { pub mod book; pub mod fee_policy; pub mod hooks; + pub mod hooks_caller; pub mod order_id; pub mod tick; pub mod tick_bitmap; diff --git a/src/libraries/hooks.cairo b/src/libraries/hooks.cairo index 1f57b39..fd30842 100644 --- a/src/libraries/hooks.cairo +++ b/src/libraries/hooks.cairo @@ -1,6 +1,6 @@ use starknet::ContractAddress; -#[derive(Copy, Drop, Hash, Serde)] +#[derive(Copy, Drop, Hash, Serde, starknet::Store)] pub struct Hooks { pub address: ContractAddress, } diff --git a/src/libraries/hooks_caller.cairo b/src/libraries/hooks_caller.cairo new file mode 100644 index 0000000..2dfd108 --- /dev/null +++ b/src/libraries/hooks_caller.cairo @@ -0,0 +1,202 @@ +use starknet::{SyscallResultTrait, ContractAddress, syscalls, get_caller_address}; +use starknet::storage::Map; +use openzeppelin_utils::structs::storage_array::{StorageArray, StorageArrayTrait}; +use clober_cairo::utils::constants::ZERO_ADDRESS; +use clober_cairo::libraries::hooks::{Hooks, HooksTrait, Permission}; +use clober_cairo::libraries::book_key::BookKey; +use clober_cairo::interfaces::params::{MakeParams, TakeParams, CancelParams}; + +#[derive(Copy, Drop, starknet::Store)] +pub struct HooksCaller { + pub hooks_list: StorageArray, +} + +#[generate_trait] +pub impl HooksCallerImpl of HooksCallerTrait { + fn get_current_hook(self: @HooksCaller) -> ContractAddress { + let length = self.hooks_list.len(); + if length == 0 { + ZERO_ADDRESS() + } else { + self.hooks_list.read_at(length - 1).address + } + } + + fn get_hook(self: @HooksCaller, i: u32) -> ContractAddress { + self.hooks_list.read_at(i).address + } + + fn call_hook( + ref self: HooksCaller, hooks: @Hooks, expected_selector: felt252, hook_data: Span + ) { + // @dev Set current hook here + self.hooks_list.append(*hooks); + + let mut res = syscalls::call_contract_syscall(*hooks.address, expected_selector, hook_data) + .unwrap_syscall(); + + let selector = Serde::::deserialize(ref res).unwrap(); + + // @dev Clear current hook here + // TODO: check this + // self.hooks_list.pop(); + + assert(selector == expected_selector, 'InvalidHookResponse'); + } + + fn before_open(ref self: HooksCaller, hooks: @Hooks, key: @BookKey, hook_data: Span) { + if (hooks.has_permission(Permission::BEFORE_OPEN)) { + let caller = get_caller_address(); + let mut data: Array = ArrayTrait::new(); + Serde::serialize(@caller, ref data); + Serde::serialize(key, ref data); + Serde::serialize(@hook_data, ref data); + + self.call_hook(hooks, selector!("before_open"), data.span()); + } + } + + fn after_open(ref self: HooksCaller, hooks: @Hooks, key: @BookKey, hook_data: Span) { + if (hooks.has_permission(Permission::AFTER_OPEN)) { + let caller = get_caller_address(); + let mut data: Array = ArrayTrait::new(); + Serde::serialize(@caller, ref data); + Serde::serialize(key, ref data); + Serde::serialize(@hook_data, ref data); + + self.call_hook(hooks, selector!("after_open"), data.span()); + } + } + + fn before_make( + ref self: HooksCaller, hooks: @Hooks, params: @MakeParams, hook_data: Span + ) { + if (hooks.has_permission(Permission::BEFORE_MAKE)) { + let caller = get_caller_address(); + let mut data: Array = ArrayTrait::new(); + Serde::serialize(@caller, ref data); + Serde::serialize(params, ref data); + Serde::serialize(@data, ref data); + + self.call_hook(hooks, selector!("before_make"), data.span()); + } + } + + fn after_make( + ref self: HooksCaller, + hooks: @Hooks, + params: @MakeParams, + order_id: felt252, + hook_data: Span + ) { + if (hooks.has_permission(Permission::AFTER_MAKE)) { + let caller = get_caller_address(); + let mut data: Array = ArrayTrait::new(); + Serde::serialize(@caller, ref data); + Serde::serialize(params, ref data); + Serde::serialize(@order_id, ref data); + Serde::serialize(@data, ref data); + + self.call_hook(hooks, selector!("after_make"), data.span()); + } + } + + fn before_take( + ref self: HooksCaller, hooks: @Hooks, params: @TakeParams, hook_data: Span + ) { + if (hooks.has_permission(Permission::BEFORE_TAKE)) { + let caller = get_caller_address(); + let mut data: Array = ArrayTrait::new(); + Serde::serialize(@caller, ref data); + Serde::serialize(params, ref data); + Serde::serialize(@data, ref data); + + self.call_hook(hooks, selector!("before_take"), data.span()); + } + } + + fn after_take( + ref self: HooksCaller, + hooks: @Hooks, + params: @TakeParams, + taken_unit: u64, + hook_data: Span + ) { + if (hooks.has_permission(Permission::AFTER_TAKE)) { + let caller = get_caller_address(); + let mut data: Array = ArrayTrait::new(); + Serde::serialize(@caller, ref data); + Serde::serialize(params, ref data); + Serde::serialize(@taken_unit, ref data); + Serde::serialize(@data, ref data); + + self.call_hook(hooks, selector!("after_take"), data.span()); + } + } + + fn before_cancel( + ref self: HooksCaller, hooks: @Hooks, params: @CancelParams, hook_data: Span + ) { + if (hooks.has_permission(Permission::BEFORE_CANCEL)) { + let caller = get_caller_address(); + let mut data: Array = ArrayTrait::new(); + Serde::serialize(@caller, ref data); + Serde::serialize(params, ref data); + Serde::serialize(@data, ref data); + + self.call_hook(hooks, selector!("before_cancel"), data.span()); + } + } + + fn after_cancel( + ref self: HooksCaller, + hooks: @Hooks, + params: @CancelParams, + canceled_unit: u64, + hook_data: Span + ) { + if (hooks.has_permission(Permission::AFTER_CANCEL)) { + let caller = get_caller_address(); + let mut data: Array = ArrayTrait::new(); + Serde::serialize(@caller, ref data); + Serde::serialize(params, ref data); + Serde::serialize(@canceled_unit, ref data); + Serde::serialize(@data, ref data); + + self.call_hook(hooks, selector!("after_cancel"), data.span()); + } + } + + fn before_claim( + ref self: HooksCaller, hooks: @Hooks, order_id: felt252, hook_data: Span + ) { + if (hooks.has_permission(Permission::BEFORE_CLAIM)) { + let caller = get_caller_address(); + let mut data: Array = ArrayTrait::new(); + Serde::serialize(@caller, ref data); + Serde::serialize(@order_id, ref data); + Serde::serialize(@data, ref data); + + self.call_hook(hooks, selector!("before_claim"), data.span()); + } + } + + fn after_claim( + ref self: HooksCaller, + hooks: @Hooks, + order_id: felt252, + claimed_unit: u64, + hook_data: Span + ) { + if (hooks.has_permission(Permission::AFTER_CLAIM)) { + let caller = get_caller_address(); + let mut data: Array = ArrayTrait::new(); + Serde::serialize(@caller, ref data); + Serde::serialize(@order_id, ref data); + Serde::serialize(@claimed_unit, ref data); + Serde::serialize(@data, ref data); + + self.call_hook(hooks, selector!("after_claim"), data.span()); + } + } +}