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;
}