From 70eeab39e865446f44d896899fa0fc0a2b6ae5b8 Mon Sep 17 00:00:00 2001 From: Credence Date: Wed, 4 Oct 2023 00:57:36 +0100 Subject: [PATCH 1/2] refactor(dojo-defi): use dojo 0.3.0 syntax --- crates/dojo-defi/src/market/models.cairo | 39 +++++++-- crates/dojo-defi/src/market/systems.cairo | 97 +++++++++++------------ 2 files changed, 77 insertions(+), 59 deletions(-) diff --git a/crates/dojo-defi/src/market/models.cairo b/crates/dojo-defi/src/market/models.cairo index c7da959dfe..1bc694c539 100644 --- a/crates/dojo-defi/src/market/models.cairo +++ b/crates/dojo-defi/src/market/models.cairo @@ -1,5 +1,5 @@ use starknet::ContractAddress; -use dojo::model::StorageIntrospection; +use dojo::database::schema::{Struct, Ty, SchemaIntrospection, Member, serialize_member}; // Cubit fixed point math library use cubit::f128::types::fixed::Fixed; @@ -8,19 +8,42 @@ const SCALING_FACTOR: u128 = 10000; impl SchemaIntrospectionFixed of SchemaIntrospection { #[inline(always)] - fn unpacked_size() -> usize { - 1 + fn size() -> usize { + SchemaIntrospection::::size() + + SchemaIntrospection::::size() } #[inline(always)] - fn packed_size() -> usize { - 129 + fn layout(ref layout: Array) { + SchemaIntrospection::::layout(ref layout); + SchemaIntrospection::::layout(ref layout); } #[inline(always)] - fn layout(ref layout: Array) { - layout.append(128); - layout.append(1); + fn ty() -> Ty { + Ty::Struct( + Struct { + name: 'Fixed', + attrs: array![].span(), + children: array![ + serialize_member( + @Member { + name: 'mag', + ty: SchemaIntrospection::::ty(), + attrs: array![].span() + } + ), + serialize_member( + @Member { + name: 'sign', + ty: SchemaIntrospection::::ty(), + attrs: array![].span() + } + ) + ] + .span() + } + ) } } diff --git a/crates/dojo-defi/src/market/systems.cairo b/crates/dojo-defi/src/market/systems.cairo index 078bd5cec1..1f557eca53 100644 --- a/crates/dojo-defi/src/market/systems.cairo +++ b/crates/dojo-defi/src/market/systems.cairo @@ -1,22 +1,24 @@ #[system] -mod Buy { +mod Trade { use dojo_defi::market::models::{Item, Cash, Market}; use dojo_defi::market::constant_product_market::MarketTrait; - use dojo::world::Context; - fn execute(ctx: Context, item_id: u32, quantity: u128) { + + #[external(v0)] + fn buy(self: @ContractState, world: IWorldDispatcher, item_id: u32, quantity: u128) { + let player = starknet::get_caller_address(); - let player_cash = get!(ctx.world, (player), Cash); + let player_cash = get!(world, (player), Cash); - let market = get!(ctx.world, (item_id), Market); + let market = get!(world, (item_id), Market); let cost = market.buy(quantity); assert(cost <= player_cash.amount, 'not enough cash'); // update market set!( - ctx.world, + world, (Market { item_id: item_id, cash_amount: market.cash_amount + cost, @@ -25,38 +27,34 @@ mod Buy { ); // update player cash - set!(ctx.world, (Cash { player: player, amount: player_cash.amount - cost })); + set!(world, (Cash { player: player, amount: player_cash.amount - cost })); // update player item - let item = get!(ctx.world, (player, item_id), Item); + let item = get!(world, (player, item_id), Item); set!( - ctx.world, + world, (Item { player: player, item_id: item_id, quantity: item.quantity + quantity }) ); } -} -#[system] -mod Sell { - use dojo_defi::market::models::{Item, Cash, Market}; - use dojo_defi::market::constant_product_market::MarketTrait; - use dojo::world::Context; - fn execute(ctx: Context, item_id: u32, quantity: u128) { + + #[external(v0)] + fn sell(self: @ContractState, world: IWorldDispatcher, item_id: u32, quantity: u128) { let player = starknet::get_caller_address(); - let item = get!(ctx.world, (player, item_id), Item); + let item = get!(world, (player, item_id), Item); let player_quantity = item.quantity; assert(player_quantity >= quantity, 'not enough items'); - let player_cash = get!(ctx.world, (player), Cash); + let player_cash = get!(world, (player), Cash); - let market = get!(ctx.world, (item_id), Market); + let market = get!(world, (item_id), Market); let payout = market.sell(quantity); // update market set!( - ctx.world, + world, (Market { item_id: item_id, cash_amount: market.cash_amount - payout, @@ -65,38 +63,41 @@ mod Sell { ); // update player cash - set!(ctx.world, (Cash { player: player, amount: player_cash.amount + payout })); + set!(world, (Cash { player: player, amount: player_cash.amount + payout })); // update player item set!( - ctx.world, + world, (Item { player: player, item_id: item_id, quantity: player_quantity - quantity }) ); } } + #[system] -mod AddLiquidity { +mod Liquidity { use dojo_defi::market::models::{Item, Cash, Market, Liquidity}; use dojo_defi::market::constant_product_market::MarketTrait; - use dojo::world::Context; + + use cubit::f128::types::fixed::Fixed; - fn execute(ctx: Context, item_id: u32, amount: u128, quantity: u128) { + #[external(v0)] + fn add(self: @ContractState, world: IWorldDispatcher, item_id: u32, amount: u128, quantity: u128) { let player = starknet::get_caller_address(); - let item = get!(ctx.world, (player, item_id), Item); + let item = get!(world, (player, item_id), Item); let player_quantity = item.quantity; assert(player_quantity >= quantity, 'not enough items'); - let player_cash = get!(ctx.world, (player), Cash); + let player_cash = get!(world, (player), Cash); assert(amount <= player_cash.amount, 'not enough cash'); - let market = get!(ctx.world, (item_id), Market); + let market = get!(world, (item_id), Market); let (cost_cash, cost_quantity, liquidity_shares) = market.add_liquidity(amount, quantity); // update market set!( - ctx.world, + world, (Market { item_id: item_id, cash_amount: market.cash_amount + cost_cash, @@ -105,45 +106,40 @@ mod AddLiquidity { ); // update player cash - set!(ctx.world, (Cash { player: player, amount: player_cash.amount - cost_cash })); + set!(world, (Cash { player: player, amount: player_cash.amount - cost_cash })); // update player item set!( - ctx.world, + world, (Item { player: player, item_id: item_id, quantity: player_quantity - cost_quantity }) ); // update player liquidity - let player_liquidity = get!(ctx.world, (player, item_id), Liquidity); + let player_liquidity = get!(world, (player, item_id), Liquidity); set!( - ctx.world, + world, (Liquidity { player: player, item_id: item_id, shares: player_liquidity.shares + liquidity_shares }) ); } -} -#[system] -mod RemoveLiquidity { - use dojo_defi::market::models::{Item, Cash, Market, Liquidity}; - use dojo_defi::market::constant_product_market::MarketTrait; - use dojo::world::Context; - use cubit::f128::types::fixed::Fixed; - fn execute(ctx: Context, item_id: u32, shares: Fixed) { + + #[external(v0)] + fn remove(self: @ContractState, world: IWorldDispatcher, item_id: u32, shares: Fixed) { let player = starknet::get_caller_address(); - let player_liquidity = get!(ctx.world, (player, item_id), Liquidity); + let player_liquidity = get!(world, (player, item_id), Liquidity); assert(player_liquidity.shares >= shares, 'not enough shares'); - let market = get!(ctx.world, (item_id), Market); + let market = get!(world, (item_id), Market); let (payout_cash, payout_quantity) = market.remove_liquidity(shares); // update market set!( - ctx.world, + world, (Market { item_id: item_id, cash_amount: market.cash_amount - payout_cash, @@ -152,25 +148,24 @@ mod RemoveLiquidity { ); // update player cash - let player_cash = get!(ctx.world, (player), Cash); - set!(ctx.world, (Cash { player: player, amount: player_cash.amount + payout_cash })); + let player_cash = get!(world, (player), Cash); + set!(world, (Cash { player: player, amount: player_cash.amount + payout_cash })); // update player item - let item = get!(ctx.world, (player, item_id), Item); + let item = get!(world, (player, item_id), Item); let player_quantity = item.quantity; set!( - ctx.world, + world, (Item { player: player, item_id: item_id, quantity: player_quantity + payout_quantity }) ); // update player liquidity - let player_liquidity = get!(ctx.world, (player, item_id), Liquidity); + let player_liquidity = get!(world, (player, item_id), Liquidity); set!( - ctx.world, + world, (Liquidity { player: player, item_id: item_id, shares: player_liquidity.shares - shares }) ); } } - From 6f796c9aebba1c1385d024b7d5881aed62d4813b Mon Sep 17 00:00:00 2001 From: Credence Date: Wed, 4 Oct 2023 17:03:10 +0100 Subject: [PATCH 2/2] refactor(dojo-defi): use traits with contracts --- crates/dojo-defi/src/market/systems.cairo | 320 ++++++++++++---------- 1 file changed, 172 insertions(+), 148 deletions(-) diff --git a/crates/dojo-defi/src/market/systems.cairo b/crates/dojo-defi/src/market/systems.cairo index 1f557eca53..27d9b10b21 100644 --- a/crates/dojo-defi/src/market/systems.cairo +++ b/crates/dojo-defi/src/market/systems.cairo @@ -1,171 +1,195 @@ +use cubit::f128::types::fixed::Fixed; +use dojo::world::IWorldDispatcher; + + +trait ITrade { + fn buy(self: @TContractState, world: IWorldDispatcher, item_id: u32, quantity: u128); + fn sell(self: @TContractState, world: IWorldDispatcher, item_id: u32, quantity: u128); +} + + #[system] mod Trade { use dojo_defi::market::models::{Item, Cash, Market}; use dojo_defi::market::constant_product_market::MarketTrait; + use super::ITrade; + #[external(v0)] - fn buy(self: @ContractState, world: IWorldDispatcher, item_id: u32, quantity: u128) { - - let player = starknet::get_caller_address(); - - let player_cash = get!(world, (player), Cash); - - let market = get!(world, (item_id), Market); - - let cost = market.buy(quantity); - assert(cost <= player_cash.amount, 'not enough cash'); - - // update market - set!( - world, - (Market { - item_id: item_id, - cash_amount: market.cash_amount + cost, - item_quantity: market.item_quantity - quantity, - }) - ); - - // update player cash - set!(world, (Cash { player: player, amount: player_cash.amount - cost })); - - // update player item - let item = get!(world, (player, item_id), Item); - set!( - world, - (Item { player: player, item_id: item_id, quantity: item.quantity + quantity }) - ); - } + impl TradeImpl of ITrade { + fn buy(self: @ContractState, world: IWorldDispatcher, item_id: u32, quantity: u128) { + + let player = starknet::get_caller_address(); + let player_cash = get!(world, (player), Cash); + let market = get!(world, (item_id), Market); + + let cost = market.buy(quantity); + assert(cost <= player_cash.amount, 'not enough cash'); + + // update market + set!( + world, + (Market { + item_id: item_id, + cash_amount: market.cash_amount + cost, + item_quantity: market.item_quantity - quantity, + }) + ); + + // update player cash + set!(world, (Cash { player: player, amount: player_cash.amount - cost })); + + // update player item + let item = get!(world, (player, item_id), Item); + set!( + world, + (Item { player: player, item_id: item_id, quantity: item.quantity + quantity }) + ); + } + + + + fn sell(self: @ContractState, world: IWorldDispatcher, item_id: u32, quantity: u128) { + let player = starknet::get_caller_address(); + + let item = get!(world, (player, item_id), Item); + let player_quantity = item.quantity; + assert(player_quantity >= quantity, 'not enough items'); + + let player_cash = get!(world, (player), Cash); + + let market = get!(world, (item_id), Market); + let payout = market.sell(quantity); + + // update market + set!( + world, + (Market { + item_id: item_id, + cash_amount: market.cash_amount - payout, + item_quantity: market.item_quantity + quantity, + }) + ); + + // update player cash + set!(world, (Cash { player: player, amount: player_cash.amount + payout })); + + // update player item + set!( + world, + (Item { player: player, item_id: item_id, quantity: player_quantity - quantity }) + ); + } - #[external(v0)] - fn sell(self: @ContractState, world: IWorldDispatcher, item_id: u32, quantity: u128) { - let player = starknet::get_caller_address(); - - let item = get!(world, (player, item_id), Item); - let player_quantity = item.quantity; - assert(player_quantity >= quantity, 'not enough items'); - - let player_cash = get!(world, (player), Cash); - - let market = get!(world, (item_id), Market); - let payout = market.sell(quantity); - - // update market - set!( - world, - (Market { - item_id: item_id, - cash_amount: market.cash_amount - payout, - item_quantity: market.item_quantity + quantity, - }) - ); - - // update player cash - set!(world, (Cash { player: player, amount: player_cash.amount + payout })); - - // update player item - set!( - world, - (Item { player: player, item_id: item_id, quantity: player_quantity - quantity }) - ); } + +} + + + +trait ILiquidity { + fn add(self: @TContractState, world: IWorldDispatcher, item_id: u32, amount: u128, quantity: u128); + fn remove(self: @TContractState, world: IWorldDispatcher, item_id: u32, shares: Fixed); } #[system] mod Liquidity { + use cubit::f128::types::fixed::Fixed; + use dojo_defi::market::models::{Item, Cash, Market, Liquidity}; use dojo_defi::market::constant_product_market::MarketTrait; - use cubit::f128::types::fixed::Fixed; + use super::ILiquidity; #[external(v0)] - fn add(self: @ContractState, world: IWorldDispatcher, item_id: u32, amount: u128, quantity: u128) { - let player = starknet::get_caller_address(); - - let item = get!(world, (player, item_id), Item); - let player_quantity = item.quantity; - assert(player_quantity >= quantity, 'not enough items'); - - let player_cash = get!(world, (player), Cash); - assert(amount <= player_cash.amount, 'not enough cash'); - - let market = get!(world, (item_id), Market); - let (cost_cash, cost_quantity, liquidity_shares) = market.add_liquidity(amount, quantity); - - // update market - set!( - world, - (Market { - item_id: item_id, - cash_amount: market.cash_amount + cost_cash, - item_quantity: market.item_quantity + cost_quantity - }) - ); - - // update player cash - set!(world, (Cash { player: player, amount: player_cash.amount - cost_cash })); - - // update player item - set!( - world, - (Item { player: player, item_id: item_id, quantity: player_quantity - cost_quantity }) - ); - - // update player liquidity - let player_liquidity = get!(world, (player, item_id), Liquidity); - set!( - world, - (Liquidity { - player: player, item_id: item_id, shares: player_liquidity.shares + liquidity_shares - }) - ); - } - - - - - #[external(v0)] - fn remove(self: @ContractState, world: IWorldDispatcher, item_id: u32, shares: Fixed) { - let player = starknet::get_caller_address(); - - let player_liquidity = get!(world, (player, item_id), Liquidity); - assert(player_liquidity.shares >= shares, 'not enough shares'); - - let market = get!(world, (item_id), Market); - let (payout_cash, payout_quantity) = market.remove_liquidity(shares); - - // update market - set!( - world, - (Market { - item_id: item_id, - cash_amount: market.cash_amount - payout_cash, - item_quantity: market.item_quantity - payout_quantity - }) - ); - - // update player cash - let player_cash = get!(world, (player), Cash); - set!(world, (Cash { player: player, amount: player_cash.amount + payout_cash })); - - // update player item - let item = get!(world, (player, item_id), Item); - let player_quantity = item.quantity; - set!( - world, - (Item { player: player, item_id: item_id, quantity: player_quantity + payout_quantity }) - ); - - // update player liquidity - let player_liquidity = get!(world, (player, item_id), Liquidity); - set!( - world, - (Liquidity { - player: player, item_id: item_id, shares: player_liquidity.shares - shares - }) - ); + impl LiquidityImpl of ILiquidity { + + fn add(self: @ContractState, world: IWorldDispatcher, item_id: u32, amount: u128, quantity: u128) { + let player = starknet::get_caller_address(); + + let item = get!(world, (player, item_id), Item); + let player_quantity = item.quantity; + assert(player_quantity >= quantity, 'not enough items'); + + let player_cash = get!(world, (player), Cash); + assert(amount <= player_cash.amount, 'not enough cash'); + + let market = get!(world, (item_id), Market); + let (cost_cash, cost_quantity, liquidity_shares) = market.add_liquidity(amount, quantity); + + // update market + set!( + world, + (Market { + item_id: item_id, + cash_amount: market.cash_amount + cost_cash, + item_quantity: market.item_quantity + cost_quantity + }) + ); + + // update player cash + set!(world, (Cash { player: player, amount: player_cash.amount - cost_cash })); + + // update player item + set!( + world, + (Item { player: player, item_id: item_id, quantity: player_quantity - cost_quantity }) + ); + + // update player liquidity + let player_liquidity = get!(world, (player, item_id), Liquidity); + set!( + world, + (Liquidity { + player: player, item_id: item_id, shares: player_liquidity.shares + liquidity_shares + }) + ); + } + + + fn remove(self: @ContractState, world: IWorldDispatcher, item_id: u32, shares: Fixed) { + let player = starknet::get_caller_address(); + + let player_liquidity = get!(world, (player, item_id), Liquidity); + assert(player_liquidity.shares >= shares, 'not enough shares'); + + let market = get!(world, (item_id), Market); + let (payout_cash, payout_quantity) = market.remove_liquidity(shares); + + // update market + set!( + world, + (Market { + item_id: item_id, + cash_amount: market.cash_amount - payout_cash, + item_quantity: market.item_quantity - payout_quantity + }) + ); + + // update player cash + let player_cash = get!(world, (player), Cash); + set!(world, (Cash { player: player, amount: player_cash.amount + payout_cash })); + + // update player item + let item = get!(world, (player, item_id), Item); + let player_quantity = item.quantity; + set!( + world, + (Item { player: player, item_id: item_id, quantity: player_quantity + payout_quantity }) + ); + + // update player liquidity + let player_liquidity = get!(world, (player, item_id), Liquidity); + set!( + world, + (Liquidity { + player: player, item_id: item_id, shares: player_liquidity.shares - shares + }) + ); + } } }