From c9ee8f4330a5a55151013e48cbe5916de0c1ddd0 Mon Sep 17 00:00:00 2001 From: Patrice Tisserand Date: Tue, 27 Aug 2024 19:39:40 +0200 Subject: [PATCH] feat(executor): add `get_fees_amount` view to retrieve fees for a given token --- contracts/ark_starknet/src/executor.cairo | 72 ++++++++++++--- contracts/ark_starknet/src/interfaces.cairo | 16 ++++ .../tests/integration/fees_amount.cairo | 89 +++++++++++++++++++ contracts/ark_starknet/tests/lib.cairo | 1 + 4 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 contracts/ark_starknet/tests/integration/fees_amount.cairo diff --git a/contracts/ark_starknet/src/executor.cairo b/contracts/ark_starknet/src/executor.cairo index 08f8652b9..acc26d7f3 100644 --- a/contracts/ark_starknet/src/executor.cairo +++ b/contracts/ark_starknet/src/executor.cairo @@ -76,6 +76,7 @@ mod executor { use ark_oz::erc2981::{FeesRatio, FeesRatioDefault, FeesImpl}; use ark_starknet::interfaces::{IExecutor, IUpgradable}; + use ark_starknet::interfaces::FeesAmount; use ark_starknet::appchain_messaging::{ IAppchainMessagingDispatcher, IAppchainMessagingDispatcherTrait, @@ -222,6 +223,32 @@ mod executor { self.creator_fees.write(nft_address, (receiver, fees_ratio)); } + fn get_fees_amount( + self: @ContractState, + fulfill_broker: ContractAddress, + listing_broker: ContractAddress, + nft_address: ContractAddress, + nft_token_id: u256, + payment_amount: u256 + ) -> FeesAmount { + let ( + fulfill_broker_fees_amount, + listing_broker_fees_amount, + ark_fees_amount, + creator_fees_amount + ) = + _compute_fees_amount( + self, fulfill_broker, listing_broker, nft_address, nft_token_id, payment_amount + ); + + FeesAmount { + fulfill_broker: fulfill_broker_fees_amount, + listing_broker: listing_broker_fees_amount, + ark: ark_fees_amount, + creator: creator_fees_amount, + } + } + fn get_messaging_address(self: @ContractState) -> ContractAddress { self.messaging_address.read() } @@ -355,22 +382,21 @@ mod executor { contract_address: execution_info.payment_currency_address.try_into().unwrap() }; - let fulfill_broker_fees = self.get_broker_fees(execution_info.fulfill_broker_address); - let listing_broker_fees = self.get_broker_fees(execution_info.listing_broker_address); - let ark_fees = self.ark_fees.read(); - - let fulfill_broker_fees_amount = fulfill_broker_fees - .compute_amount(execution_info.payment_amount); - let listing_broker_fees_amount = listing_broker_fees - .compute_amount(execution_info.payment_amount); let (creator_address, creator_fees_amount) = _compute_creator_fees_amount( @self, @execution_info.nft_address, execution_info.payment_amount, execution_info.nft_token_id ); - let ark_fees_amount = ark_fees.compute_amount(execution_info.payment_amount); - + let (fulfill_broker_fees_amount, listing_broker_fees_amount, ark_fees_amount, _) = + _compute_fees_amount( + @self, + execution_info.fulfill_broker_address, + execution_info.listing_broker_address, + execution_info.nft_address, + execution_info.nft_token_id, + execution_info.payment_amount + ); assert!( execution_info .payment_amount > (fulfill_broker_fees_amount @@ -772,4 +798,30 @@ mod executor { let amount = fees_ratio.compute_amount(payment_amount); (receiver, amount) } + + fn _compute_fees_amount( + self: @ContractState, + fulfill_broker_address: ContractAddress, + listing_broker_address: ContractAddress, + nft_address: ContractAddress, + nft_token_id: u256, + payment_amount: u256 + ) -> (u256, u256, u256, u256) { + let fulfill_broker_fees = self.get_broker_fees(fulfill_broker_address); + let listing_broker_fees = self.get_broker_fees(listing_broker_address); + let ark_fees = self.ark_fees.read(); + + let fulfill_broker_fees_amount = fulfill_broker_fees.compute_amount(payment_amount); + let listing_broker_fees_amount = listing_broker_fees.compute_amount(payment_amount); + let (_, creator_fees_amount) = _compute_creator_fees_amount( + self, @nft_address, payment_amount, nft_token_id + ); + let ark_fees_amount = ark_fees.compute_amount(payment_amount); + ( + fulfill_broker_fees_amount, + listing_broker_fees_amount, + ark_fees_amount, + creator_fees_amount, + ) + } } diff --git a/contracts/ark_starknet/src/interfaces.cairo b/contracts/ark_starknet/src/interfaces.cairo index f12c3ee80..c8f1b8260 100644 --- a/contracts/ark_starknet/src/interfaces.cairo +++ b/contracts/ark_starknet/src/interfaces.cairo @@ -5,6 +5,13 @@ use ark_common::protocol::order_types::OrderV1; use ark_common::protocol::order_types::{FulfillInfo, CancelInfo}; use ark_oz::erc2981::FeesRatio; +#[derive(Serde, Drop)] +struct FeesAmount { + fulfill_broker: u256, + listing_broker: u256, + ark: u256, + creator: u256, +} #[starknet::interface] trait IExecutor { @@ -32,6 +39,15 @@ trait IExecutor { fn set_collection_creator_fees( ref self: T, nft_address: ContractAddress, receiver: ContractAddress, fees_ratio: FeesRatio ); + + fn get_fees_amount( + self: @T, + fulfill_broker: ContractAddress, + listing_broker: ContractAddress, + nft_address: ContractAddress, + nft_token_id: u256, + payment_amount: u256 + ) -> FeesAmount; } #[starknet::interface] diff --git a/contracts/ark_starknet/tests/integration/fees_amount.cairo b/contracts/ark_starknet/tests/integration/fees_amount.cairo new file mode 100644 index 000000000..23d90c4ec --- /dev/null +++ b/contracts/ark_starknet/tests/integration/fees_amount.cairo @@ -0,0 +1,89 @@ +use starknet::{ContractAddress, contract_address_const}; + +use ark_starknet::interfaces::{ + IExecutorDispatcher, IExecutorDispatcherTrait, FeesAmount, FeesRatio +}; + +use snforge_std as snf; +use snf::{ContractClass, ContractClassTrait, CheatTarget}; + +use super::super::common::setup::setup; + + +#[test] +fn test_get_fees_amount_default_creator() { + let admin = contract_address_const::<'admin'>(); + let creator = contract_address_const::<'creator'>(); + let listing_broker = contract_address_const::<'listing_broker'>(); + let fulfill_broker = contract_address_const::<'fulfill_broker'>(); + + let amount = 10_000_000; + let (executor_address, _, nft_address) = setup(); + let executor = IExecutorDispatcher { contract_address: executor_address }; + + let fulfill_fees_ratio = FeesRatio { numerator: 10, denominator: 100 }; + let listing_fees_ratio = FeesRatio { numerator: 5, denominator: 100 }; + let ark_fees_ratio = FeesRatio { numerator: 1, denominator: 100 }; + let default_creator_fees_ratio = FeesRatio { numerator: 2, denominator: 100 }; + + snf::start_prank(CheatTarget::One(executor.contract_address), fulfill_broker); + executor.set_broker_fees(fulfill_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + + snf::start_prank(CheatTarget::One(executor.contract_address), listing_broker); + executor.set_broker_fees(listing_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + + snf::start_prank(CheatTarget::One(executor.contract_address), admin); + executor.set_ark_fees(ark_fees_ratio); + executor.set_default_creator_fees(creator, default_creator_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + + let fees_amount = executor + .get_fees_amount(fulfill_broker, listing_broker, nft_address, 1, amount); + + assert_eq!(fees_amount.fulfill_broker, 1_000_000, "Wrong amount for fulfill broker"); + assert_eq!(fees_amount.listing_broker, 500_000, "Wrong amount for listing broker"); + assert_eq!(fees_amount.ark, 100_000, "Wrong amount for Ark"); + assert_eq!(fees_amount.creator, 200_000, "Wrong amount for creator"); +} + +#[test] +fn test_get_fees_amount_collection_creator() { + let admin = contract_address_const::<'admin'>(); + let creator = contract_address_const::<'creator'>(); + let listing_broker = contract_address_const::<'listing_broker'>(); + let fulfill_broker = contract_address_const::<'fulfill_broker'>(); + + let amount = 10_000_000; + let (executor_address, _, nft_address) = setup(); + let executor = IExecutorDispatcher { contract_address: executor_address }; + + let fulfill_fees_ratio = FeesRatio { numerator: 10, denominator: 100 }; + let listing_fees_ratio = FeesRatio { numerator: 5, denominator: 100 }; + let ark_fees_ratio = FeesRatio { numerator: 1, denominator: 100 }; + let default_creator_fees_ratio = FeesRatio { numerator: 2, denominator: 100 }; + let collection_creator_fees_ratio = FeesRatio { numerator: 3, denominator: 100 }; + + snf::start_prank(CheatTarget::One(executor.contract_address), fulfill_broker); + executor.set_broker_fees(fulfill_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + + snf::start_prank(CheatTarget::One(executor.contract_address), listing_broker); + executor.set_broker_fees(listing_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + + snf::start_prank(CheatTarget::One(executor.contract_address), admin); + executor.set_ark_fees(ark_fees_ratio); + executor.set_default_creator_fees(creator, default_creator_fees_ratio); + executor.set_collection_creator_fees(nft_address, creator, collection_creator_fees_ratio); + snf::stop_prank(CheatTarget::One(executor.contract_address)); + + let fees_amount = executor + .get_fees_amount(fulfill_broker, listing_broker, nft_address, 1, amount); + + assert_eq!(fees_amount.fulfill_broker, 1_000_000, "Wrong amount for fulfill broker"); + assert_eq!(fees_amount.listing_broker, 500_000, "Wrong amount for listing broker"); + assert_eq!(fees_amount.ark, 100_000, "Wrong amount for Ark"); + assert_eq!(fees_amount.creator, 300_000, "Wrong amount for creator"); +} diff --git a/contracts/ark_starknet/tests/lib.cairo b/contracts/ark_starknet/tests/lib.cairo index a70646ef0..d5281d87a 100644 --- a/contracts/ark_starknet/tests/lib.cairo +++ b/contracts/ark_starknet/tests/lib.cairo @@ -7,6 +7,7 @@ mod unit { } mod integration { mod create_order; + mod fees_amount; mod fulfill_order; mod execute_order; }