@@ -8,7 +8,8 @@ use margin_trading::{
88 margin_registry::{MarginRegistry , MaintainerCap , MarginPoolCap },
99 margin_state::{Self , State },
1010 position_manager::{Self , PositionManager },
11- protocol_config::{InterestConfig , MarginPoolConfig , ProtocolConfig }
11+ protocol_config::{InterestConfig , MarginPoolConfig , ProtocolConfig },
12+ protocol_fees::{Self , ProtocolFees , Referral }
1213};
1314use std::type_name::{Self , TypeName };
1415use sui::{balance::{Self , Balance }, clock::Clock , coin::Coin , event, vec_set::{Self , VecSet }};
@@ -29,6 +30,7 @@ public struct MarginPool<phantom Asset> has key, store {
2930 vault: Balance <Asset >,
3031 state: State ,
3132 config: ProtocolConfig ,
33+ protocol_fees: ProtocolFees ,
3234 positions: PositionManager ,
3335 allowed_deepbook_pools: VecSet <ID >,
3436}
@@ -99,6 +101,7 @@ public fun create_margin_pool<Asset>(
99101 vault: balance::zero <Asset >(),
100102 state: margin_state::default (clock),
101103 config,
104+ protocol_fees: protocol_fees::default_protocol_fees (ctx, clock),
102105 positions: position_manager::create_position_manager (ctx),
103106 allowed_deepbook_pools: vec_set::empty (),
104107 };
@@ -204,20 +207,26 @@ public fun update_margin_pool_config<Asset>(
204207}
205208
206209// === Public Functions * LENDING * ===
207- /// Allows anyone to supply the margin pool. Returns the new user supply amount.
210+ /// Supply to the margin pool. Returns the new user supply amount.
208211public fun supply <Asset >(
209212 self: &mut MarginPool <Asset >,
210213 registry: &MarginRegistry ,
211214 coin: Coin <Asset >,
215+ referral: Option <address >,
212216 clock: &Clock ,
213217 ctx: &TxContext ,
214- ) {
218+ ): u64 {
215219 registry.load_inner ();
216- let supplier = ctx.sender ();
217220 let supply_amount = coin.value ();
218-
219- let supply_shares = self.state.increase_supply (&self.config, supply_amount, clock);
220- self.positions.increase_user_supply (supplier, supply_shares);
221+ let (supply_shares, protocol_fees) = self
222+ .state
223+ .increase_supply (&self.config, supply_amount, clock);
224+ self.protocol_fees.increase_fees_per_share (self.state.supply_shares (), protocol_fees);
225+ let (total_user_supply, previous_referral) = self
226+ .positions
227+ .increase_user_supply (referral, supply_shares, ctx);
228+ self.protocol_fees.decrease_shares (previous_referral, total_user_supply - supply_shares, clock);
229+ self.protocol_fees.increase_shares (referral, total_user_supply, clock);
221230
222231 let balance = coin.into_balance ();
223232 self.vault.join (balance);
@@ -227,14 +236,16 @@ public fun supply<Asset>(
227236 event::emit (AssetSupplied {
228237 margin_pool_id: self.id (),
229238 asset_type: type_name::with_defining_ids <Asset >(),
230- supplier,
239+ supplier: ctx. sender () ,
231240 supply_amount,
232241 supply_shares,
233242 timestamp: clock.timestamp_ms (),
234243 });
244+
245+ total_user_supply
235246}
236247
237- /// Allows withdrawal from the margin pool. Returns the withdrawn coin.
248+ /// Withdraw from the margin pool. Returns the withdrawn coin.
238249public fun withdraw <Asset >(
239250 self: &mut MarginPool <Asset >,
240251 registry: &MarginRegistry ,
@@ -243,20 +254,25 @@ public fun withdraw<Asset>(
243254 ctx: &mut TxContext ,
244255): Coin <Asset > {
245256 registry.load_inner ();
246- let supplier = ctx.sender ();
247- let supplied_shares = self.positions.user_supply_shares (supplier);
257+ let supplied_shares = self.positions.user_supply_shares (ctx);
248258 let supplied_amount = self.state.supply_shares_to_amount (supplied_shares, &self.config, clock);
249259 let withdraw_amount = amount.destroy_with_default (supplied_amount);
250260 let withdraw_shares = math::mul (supplied_shares, math::div (withdraw_amount, supplied_amount));
251261
252- self.positions.decrease_user_supply (supplier, withdraw_shares);
262+ let (_, protocol_fees) = self
263+ .state
264+ .decrease_supply_shares (&self.config, withdraw_shares, clock);
265+ self.protocol_fees.increase_fees_per_share (self.state.supply_shares (), protocol_fees);
266+
267+ let (_, previous_referral) = self.positions.decrease_user_supply (withdraw_shares, ctx);
268+ self.protocol_fees.decrease_shares (previous_referral, withdraw_shares, clock);
253269 assert ! (withdraw_amount <= self.vault.value (), ENotEnoughAssetInPool );
254270 let coin = self.vault.split (withdraw_amount).into_coin (ctx);
255271
256272 event::emit (AssetWithdrawn {
257273 margin_pool_id: self.id (),
258274 asset_type: type_name::with_defining_ids <Asset >(),
259- supplier,
275+ supplier: ctx. sender () ,
260276 withdraw_amount,
261277 withdraw_shares,
262278 timestamp: clock.timestamp_ms (),
@@ -265,6 +281,19 @@ public fun withdraw<Asset>(
265281 coin
266282}
267283
284+ /// Withdraw the referral fees.
285+ public fun withdraw_referral_fees <Asset >(
286+ self: &mut MarginPool <Asset >,
287+ referral: &mut Referral ,
288+ clock: &Clock ,
289+ ctx: &mut TxContext ,
290+ ): Coin <Asset > {
291+ let referral_fees = self.protocol_fees.calculate_and_claim (referral, clock);
292+ let coin = self.vault.split (referral_fees).into_coin (ctx);
293+
294+ coin
295+ }
296+
268297// === Public-View Functions ===
269298public fun deepbook_pool_allowed <Asset >(self: &MarginPool <Asset >, deepbook_pool_id: ID ): bool {
270299 self.allowed_deepbook_pools.contains (&deepbook_pool_id)
@@ -280,9 +309,10 @@ public(package) fun borrow<Asset>(
280309): (Coin <Asset >, u64 , u64 ) {
281310 assert ! (amount <= self.vault.value (), ENotEnoughAssetInPool );
282311 assert ! (amount >= self.config.min_borrow (), EBorrowAmountTooLow );
283- let (total_borrow, total_borrow_shares) = self
312+ let (total_borrow, total_borrow_shares, protocol_fees ) = self
284313 .state
285314 .increase_borrow (&self.config, amount, clock);
315+ self.protocol_fees.increase_fees_per_share (self.state.supply_shares (), protocol_fees);
286316 assert ! (
287317 self.state.utilization_rate () <= self.config.max_utilization_rate (),
288318 EMaxPoolBorrowPercentageExceeded ,
@@ -297,7 +327,8 @@ public(package) fun repay<Asset>(
297327 coin: Coin <Asset >,
298328 clock: &Clock ,
299329) {
300- let amount = self.state.decrease_borrow_shares (&self.config, shares, clock);
330+ let (amount, protocol_fees) = self.state.decrease_borrow_shares (&self.config, shares, clock);
331+ self.protocol_fees.increase_fees_per_share (self.state.supply_shares (), protocol_fees);
301332 assert ! (coin.value () == amount, EInvalidRepayQuantity );
302333 self.vault.join (coin.into_balance ());
303334}
@@ -311,7 +342,8 @@ public(package) fun repay_liquidation<Asset>(
311342 coin: Coin <Asset >,
312343 clock: &Clock ,
313344): (u64 , u64 , u64 ) {
314- let amount = self.state.decrease_borrow_shares (&self.config, shares, clock); // decreased 48.545 shares, 97.087 USDC
345+ let (amount, protocol_fees) = self.state.decrease_borrow_shares (&self.config, shares, clock); // decreased 48.545 shares, 97.087 USDC
346+ self.protocol_fees.increase_fees_per_share (self.state.supply_shares (), protocol_fees);
315347 let coin_value = coin.value (); // 100 USDC
316348 let (reward, default) = if (coin_value > amount) {
317349 self.state.increase_supply_absolute (coin_value - amount);
0 commit comments