diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 00000000..7af9fc37 --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +scarb 2.7.0-rc.4 diff --git a/Scarb.lock b/Scarb.lock index 326ddc5e..9b045e11 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -1,83 +1,57 @@ # Code generated by scarb DO NOT EDIT. version = 1 -[[package]] -name = "chess" -version = "0.6.0-alpha.6" -dependencies = [ - "dojo", -] - [[package]] name = "cubit" version = "1.3.0" -source = "git+https://github.com/notV4l/cubit.git?branch=cairo_2.7#cadb27aa62509ad9059dfac4f075317893f1f614" +source = "git+https://github.com/dojoengine/cubit?branch=cairo_2.7#53020b6320a10f2ab55b661be9b8d895aca945e9" [[package]] name = "dojo" -version = "0.7.2" -source = "git+https://github.com/dojoengine/dojo?tag=v0.7.2#3da5cad9fdd39b81551e0668015d88262e6c5fc4" +version = "0.7.3" +source = "git+https://github.com/dojoengine/dojo?rev=a35ddcb#a35ddcb37a7c6499ca0720b0dccd739e400031c2" dependencies = [ "dojo_plugin", ] [[package]] name = "dojo_plugin" -version = "0.3.11" -source = "git+https://github.com/dojoengine/dojo?tag=v0.3.11#1e651b5d4d3b79b14a7d8aa29a92062fcb9e6659" +version = "0.7.3" +source = "git+https://github.com/dojoengine/dojo?rev=d90b52b#d90b52b89749ac8af82f352dc08aa0b1378cfae6" [[package]] -name = "governance" -version = "0.0.0" +name = "origami_algebra" +version = "0.1.0" dependencies = [ - "dojo", + "cubit", ] [[package]] -name = "hex_map" -version = "0.0.0" +name = "origami_defi" +version = "0.1.0" dependencies = [ "cubit", - "dojo", - "origami", ] [[package]] -name = "market" -version = "0.0.0" -dependencies = [ - "cubit", - "dojo", -] +name = "origami_map" +version = "0.1.0" [[package]] -name = "matchmaker" -version = "0.0.0" -dependencies = [ - "dojo", - "origami", -] +name = "origami_random" +version = "0.1.0" [[package]] -name = "origami" -version = "0.7.2" -dependencies = [ - "cubit", - "dojo", -] +name = "origami_rating" +version = "0.1.0" [[package]] -name = "projectile" -version = "0.0.0" -dependencies = [ - "cubit", - "dojo", - "origami", -] +name = "origami_security" +version = "0.1.0" [[package]] -name = "token" -version = "0.0.0" +name = "origami_token" +version = "1.0.0-alpha.0" dependencies = [ "dojo", ] diff --git a/Scarb.toml b/Scarb.toml index 54e06304..dca968fa 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,24 +1,21 @@ [workspace] members = [ - "crates", - "examples/chess", - "examples/hex_map", - "examples/market", - "examples/matchmaker", - "examples/projectile", - "token", - "governance" -] + # Scarb dependent crates. + "crates/algebra", + "crates/defi", + "crates/map", + "crates/random", + "crates/rating", + "crates/security", -[workspace.package] -version = "0.7.2" -description = "Community-maintained libraries for Cairo" -homepage = "https://github.com/dojoengine/origami" -authors = ["bal7hazar@proton.me"] + # Sozo dependent crates. + "crates/token", +# "governance" +] [workspace.dependencies] -# cubit = { git = "https://github.com/influenceth/cubit.git" } -cubit = { git = "https://github.com/notV4l/cubit.git", branch = "cairo_2.7" } -dojo = { git = "https://github.com/dojoengine/dojo", tag = "v0.7.2" } -origami = { path = "crates" } -token = { path = "token" } +cubit = { git = "https://github.com/dojoengine/cubit", branch = "cairo_2.7" } +dojo = { git = "https://github.com/dojoengine/dojo", rev = "a35ddcb" } +starknet = "2.7.0-rc.3" + +# Scripts are not supported for virtual workspaces. diff --git a/crates/algebra/Scarb.toml b/crates/algebra/Scarb.toml new file mode 100644 index 00000000..c8318e85 --- /dev/null +++ b/crates/algebra/Scarb.toml @@ -0,0 +1,11 @@ +[package] +name = "origami_algebra" +version = "0.1.0" +description = "Algebra library for Dojo based games." +homepage = "https://github.com/dojoengine/origami/tree/main/crates/algebra" + +# TODO: update to edition 2024_07, some traits are deprecated and others no longer accessible. +# Mostly related to `AddEq` -> `AddAssign` and so on. + +[dependencies] +cubit.workspace = true diff --git a/crates/algebra/src/lib.cairo b/crates/algebra/src/lib.cairo new file mode 100644 index 00000000..347476c3 --- /dev/null +++ b/crates/algebra/src/lib.cairo @@ -0,0 +1,3 @@ +mod vec2; +mod vector; +mod matrix; diff --git a/crates/src/algebra/matrix.cairo b/crates/algebra/src/matrix.cairo similarity index 100% rename from crates/src/algebra/matrix.cairo rename to crates/algebra/src/matrix.cairo diff --git a/crates/src/algebra/vec2.cairo b/crates/algebra/src/vec2.cairo similarity index 100% rename from crates/src/algebra/vec2.cairo rename to crates/algebra/src/vec2.cairo diff --git a/crates/src/algebra/vector.cairo b/crates/algebra/src/vector.cairo similarity index 100% rename from crates/src/algebra/vector.cairo rename to crates/algebra/src/vector.cairo diff --git a/crates/src/defi/README.md b/crates/defi/README.md similarity index 100% rename from crates/src/defi/README.md rename to crates/defi/README.md diff --git a/crates/defi/Scarb.toml b/crates/defi/Scarb.toml new file mode 100644 index 00000000..264f69c4 --- /dev/null +++ b/crates/defi/Scarb.toml @@ -0,0 +1,10 @@ +[package] +name = "origami_defi" +version = "0.1.0" +description = "DeFi library for Dojo based games." +homepage = "https://github.com/dojoengine/origami/tree/main/crates/defi" +edition = "2024_07" + +[dependencies] +cubit.workspace = true +starknet.workspace = true diff --git a/crates/src/defi/auction/gda.cairo b/crates/defi/src/auction/gda.cairo similarity index 97% rename from crates/src/defi/auction/gda.cairo rename to crates/defi/src/auction/gda.cairo index d86ece3f..4e3578ef 100644 --- a/crates/src/defi/auction/gda.cairo +++ b/crates/defi/src/auction/gda.cairo @@ -7,8 +7,8 @@ use cubit::f128::types::fixed::{Fixed, FixedTrait}; /// The purchase price for a given quantity is calculated based on /// the initial price, scale factor, decay constant, and the time since /// the auction has started. -#[derive(Copy, Drop, Serde, starknet::Storage)] -struct DiscreteGDA { +#[derive(Copy, Drop, Serde, starknet::Store)] +pub struct DiscreteGDA { sold: Fixed, initial_price: Fixed, scale_factor: Fixed, @@ -16,7 +16,7 @@ struct DiscreteGDA { } #[generate_trait] -impl DiscreteGDAImpl of DiscreteGDATrait { +pub impl DiscreteGDAImpl of DiscreteGDATrait { /// Calculates the purchase price for a given quantity of the item at a specific time. /// /// # Arguments @@ -39,15 +39,15 @@ impl DiscreteGDAImpl of DiscreteGDATrait { /// A Gradual Dutch Auction represented using continuous time steps. /// The purchase price is calculated based on the initial price, /// emission rate, decay constant, and the time since the last purchase in days. -#[derive(Copy, Drop, Serde, starknet::Storage)] -struct ContinuousGDA { +#[derive(Copy, Drop, Serde, starknet::Store)] +pub struct ContinuousGDA { initial_price: Fixed, emission_rate: Fixed, decay_constant: Fixed, } #[generate_trait] -impl ContinuousGDAImpl of ContinuousGDATrait { +pub impl ContinuousGDAImpl of ContinuousGDATrait { /// Calculates the purchase price for a given quantity of the item at a specific time. /// /// # Arguments diff --git a/crates/src/defi/auction/helpers.cairo b/crates/defi/src/auction/helpers.cairo similarity index 91% rename from crates/src/defi/auction/helpers.cairo rename to crates/defi/src/auction/helpers.cairo index fe50eb1e..73482fdc 100644 --- a/crates/src/defi/auction/helpers.cairo +++ b/crates/defi/src/auction/helpers.cairo @@ -2,11 +2,11 @@ use cubit::f128::types::fixed::{Fixed, FixedTrait}; -fn to_days_fp(x: Fixed) -> Fixed { +pub fn to_days_fp(x: Fixed) -> Fixed { x / FixedTrait::new(86400, false) } -fn from_days_fp(x: Fixed) -> Fixed { +pub fn from_days_fp(x: Fixed) -> Fixed { x * FixedTrait::new(86400, false) } diff --git a/crates/src/defi/auction/vrgda.cairo b/crates/defi/src/auction/vrgda.cairo similarity index 94% rename from crates/src/defi/auction/vrgda.cairo rename to crates/defi/src/auction/vrgda.cairo index 31b6b623..47efbc2a 100644 --- a/crates/src/defi/auction/vrgda.cairo +++ b/crates/defi/src/auction/vrgda.cairo @@ -5,21 +5,21 @@ use cubit::f128::types::fixed::{Fixed, FixedTrait}; // Based on https://www.paradigm.xyz/2022/08/vrgda -trait VRGDAVarsTrait { +pub trait VRGDAVarsTrait { fn get_target_price(self: @T) -> Fixed; fn get_decay_constant(self: @T) -> Fixed; } -trait VRGDATrait { +pub trait VRGDATrait { fn get_vrgda_price(self: @T, time_since_start: Fixed, sold: Fixed) -> Fixed; fn get_reverse_vrgda_price(self: @T, time_since_start: Fixed, sold: Fixed) -> Fixed; } -trait VRGDATargetTimeTrait { +pub trait VRGDATargetTimeTrait { fn get_target_sale_time(self: @T, sold: Fixed) -> Fixed; } -impl TVRGDATrait, +VRGDATargetTimeTrait> of VRGDATrait { +pub impl TVRGDATrait, +VRGDATargetTimeTrait> of VRGDATrait { /// Calculates the VRGDA price at a specific time since the auction started. /// /// # Arguments @@ -48,14 +48,14 @@ impl TVRGDATrait, +VRGDATargetTimeTrait> of VRGDATrait< /// Represents an auction where the price decays linearly based on the target price, /// decay constant, and per-time-unit rate. #[derive(Copy, Drop, Serde, starknet::Store)] -struct LinearVRGDA { +pub struct LinearVRGDA { target_price: Fixed, decay_constant: Fixed, target_units_per_time: Fixed, } -impl LinearVRGDAVarsImpl of VRGDAVarsTrait { +pub impl LinearVRGDAVarsImpl of VRGDAVarsTrait { fn get_target_price(self: @LinearVRGDA) -> Fixed { *self.target_price } @@ -80,10 +80,10 @@ impl LinearVRGDATargetTimeImpl of VRGDATargetTimeTrait { } } -impl LinearVRGDAImpl = TVRGDATrait; +pub impl LinearVRGDAImpl = TVRGDATrait; #[derive(Copy, Drop, Serde, starknet::Store)] -struct LogisticVRGDA { +pub struct LogisticVRGDA { target_price: Fixed, decay_constant: Fixed, max_sellable: Fixed, @@ -99,7 +99,7 @@ impl LogisticVRGDAVarsImpl of VRGDAVarsTrait { } } -impl LogisticVRGDATargetTimeImpl of VRGDATargetTimeTrait { +pub impl LogisticVRGDATargetTimeImpl of VRGDATargetTimeTrait { /// Calculates the target sale time using a logistic function based on the quantity sold. /// /// # Arguments @@ -116,7 +116,7 @@ impl LogisticVRGDATargetTimeImpl of VRGDATargetTimeTrait { * ln((logistic_limit_double / (sold + logistic_limit)) - FixedTrait::ONE()) } } -impl LogisticVRGDAImpl = TVRGDATrait; +pub impl LogisticVRGDAImpl = TVRGDATrait; #[cfg(test)] diff --git a/crates/defi/src/lib.cairo b/crates/defi/src/lib.cairo new file mode 100644 index 00000000..7fa4e9b6 --- /dev/null +++ b/crates/defi/src/lib.cairo @@ -0,0 +1,5 @@ +pub mod auction { + pub mod gda; + pub mod vrgda; + pub mod helpers; +} diff --git a/governance/EXAMPLES.md b/crates/governance/EXAMPLES.md similarity index 100% rename from governance/EXAMPLES.md rename to crates/governance/EXAMPLES.md diff --git a/governance/README.md b/crates/governance/README.md similarity index 100% rename from governance/README.md rename to crates/governance/README.md diff --git a/governance/Scarb.lock b/crates/governance/Scarb.lock similarity index 100% rename from governance/Scarb.lock rename to crates/governance/Scarb.lock diff --git a/governance/Scarb.toml b/crates/governance/Scarb.toml similarity index 100% rename from governance/Scarb.toml rename to crates/governance/Scarb.toml diff --git a/governance/scripts/default_auth.sh b/crates/governance/scripts/default_auth.sh similarity index 100% rename from governance/scripts/default_auth.sh rename to crates/governance/scripts/default_auth.sh diff --git a/governance/scripts/spawn.sh b/crates/governance/scripts/spawn.sh similarity index 100% rename from governance/scripts/spawn.sh rename to crates/governance/scripts/spawn.sh diff --git a/governance/src/lib.cairo b/crates/governance/src/lib.cairo similarity index 100% rename from governance/src/lib.cairo rename to crates/governance/src/lib.cairo diff --git a/governance/src/libraries/events.cairo b/crates/governance/src/libraries/events.cairo similarity index 100% rename from governance/src/libraries/events.cairo rename to crates/governance/src/libraries/events.cairo diff --git a/governance/src/libraries/traits.cairo b/crates/governance/src/libraries/traits.cairo similarity index 100% rename from governance/src/libraries/traits.cairo rename to crates/governance/src/libraries/traits.cairo diff --git a/governance/src/models/governor.cairo b/crates/governance/src/models/governor.cairo similarity index 100% rename from governance/src/models/governor.cairo rename to crates/governance/src/models/governor.cairo diff --git a/governance/src/models/timelock.cairo b/crates/governance/src/models/timelock.cairo similarity index 100% rename from governance/src/models/timelock.cairo rename to crates/governance/src/models/timelock.cairo diff --git a/governance/src/models/token.cairo b/crates/governance/src/models/token.cairo similarity index 100% rename from governance/src/models/token.cairo rename to crates/governance/src/models/token.cairo diff --git a/governance/src/systems/governor/contract.cairo b/crates/governance/src/systems/governor/contract.cairo similarity index 100% rename from governance/src/systems/governor/contract.cairo rename to crates/governance/src/systems/governor/contract.cairo diff --git a/governance/src/systems/governor/interface.cairo b/crates/governance/src/systems/governor/interface.cairo similarity index 100% rename from governance/src/systems/governor/interface.cairo rename to crates/governance/src/systems/governor/interface.cairo diff --git a/governance/src/systems/governor/tests.cairo b/crates/governance/src/systems/governor/tests.cairo similarity index 100% rename from governance/src/systems/governor/tests.cairo rename to crates/governance/src/systems/governor/tests.cairo diff --git a/governance/src/systems/timelock/contract.cairo b/crates/governance/src/systems/timelock/contract.cairo similarity index 100% rename from governance/src/systems/timelock/contract.cairo rename to crates/governance/src/systems/timelock/contract.cairo diff --git a/governance/src/systems/timelock/interface.cairo b/crates/governance/src/systems/timelock/interface.cairo similarity index 100% rename from governance/src/systems/timelock/interface.cairo rename to crates/governance/src/systems/timelock/interface.cairo diff --git a/governance/src/systems/timelock/tests.cairo b/crates/governance/src/systems/timelock/tests.cairo similarity index 100% rename from governance/src/systems/timelock/tests.cairo rename to crates/governance/src/systems/timelock/tests.cairo diff --git a/governance/src/systems/token/contract.cairo b/crates/governance/src/systems/token/contract.cairo similarity index 100% rename from governance/src/systems/token/contract.cairo rename to crates/governance/src/systems/token/contract.cairo diff --git a/governance/src/systems/token/interface.cairo b/crates/governance/src/systems/token/interface.cairo similarity index 100% rename from governance/src/systems/token/interface.cairo rename to crates/governance/src/systems/token/interface.cairo diff --git a/governance/src/systems/token/tests.cairo b/crates/governance/src/systems/token/tests.cairo similarity index 100% rename from governance/src/systems/token/tests.cairo rename to crates/governance/src/systems/token/tests.cairo diff --git a/governance/src/utils/mock_contract.cairo b/crates/governance/src/utils/mock_contract.cairo similarity index 100% rename from governance/src/utils/mock_contract.cairo rename to crates/governance/src/utils/mock_contract.cairo diff --git a/governance/src/utils/mock_contract_upgraded.cairo b/crates/governance/src/utils/mock_contract_upgraded.cairo similarity index 100% rename from governance/src/utils/mock_contract_upgraded.cairo rename to crates/governance/src/utils/mock_contract_upgraded.cairo diff --git a/governance/src/utils/testing.cairo b/crates/governance/src/utils/testing.cairo similarity index 100% rename from governance/src/utils/testing.cairo rename to crates/governance/src/utils/testing.cairo diff --git a/crates/map/Scarb.toml b/crates/map/Scarb.toml new file mode 100644 index 00000000..2881b641 --- /dev/null +++ b/crates/map/Scarb.toml @@ -0,0 +1,8 @@ +[package] +name = "origami_map" +version = "0.1.0" +description = "Maps library for Dojo based games." +homepage = "https://github.com/dojoengine/origami/tree/main/crates/map" +edition = "2024_07" + +[dependencies] diff --git a/crates/src/map/hex/hex.cairo b/crates/map/src/hex/hex.cairo similarity index 96% rename from crates/src/map/hex/hex.cairo rename to crates/map/src/hex/hex.cairo index 6e74f543..f996cbd2 100644 --- a/crates/src/map/hex/hex.cairo +++ b/crates/map/src/hex/hex.cairo @@ -1,11 +1,6 @@ -use core::clone::Clone; -use core::traits::Into; -use core::box::BoxTrait; -use core::option::OptionTrait; -use core::array::ArrayTrait; -use origami::map::hex::{types::{HexTile, Direction, DirectionIntoFelt252}}; - -trait IHexTile { +use super::types::{HexTile, Direction, DirectionIntoFelt252}; + +pub trait IHexTile { fn new(col: u32, row: u32) -> HexTile; fn neighbor(self: HexTile, direction: Direction) -> HexTile; fn neighbor_even_y(self: HexTile, direction: Direction) -> HexTile; @@ -14,7 +9,7 @@ trait IHexTile { fn tiles_within_range(self: HexTile, range: u32) -> Array; } -impl ImplHexTile of IHexTile { +pub impl ImplHexTile of IHexTile { fn new(col: u32, row: u32) -> HexTile { HexTile { col, row } } diff --git a/crates/src/map/hex/types.cairo b/crates/map/src/hex/types.cairo similarity index 77% rename from crates/src/map/hex/types.cairo rename to crates/map/src/hex/types.cairo index a1d28a84..ec9bdf44 100644 --- a/crates/src/map/hex/types.cairo +++ b/crates/map/src/hex/types.cairo @@ -1,11 +1,11 @@ #[derive(Drop, Copy, Serde)] -struct HexTile { - col: u32, - row: u32, +pub struct HexTile { + pub col: u32, + pub row: u32, } #[derive(Drop, Copy, Serde)] -enum Direction { +pub enum Direction { East: (), NorthEast: (), NorthWest: (), @@ -14,7 +14,7 @@ enum Direction { SouthEast: (), } -impl DirectionIntoFelt252 of Into { +pub impl DirectionIntoFelt252 of Into { fn into(self: Direction) -> felt252 { match self { Direction::East => 0, diff --git a/crates/map/src/lib.cairo b/crates/map/src/lib.cairo new file mode 100644 index 00000000..5d2224c4 --- /dev/null +++ b/crates/map/src/lib.cairo @@ -0,0 +1,4 @@ +pub mod hex { + pub mod hex; + pub mod types; +} diff --git a/crates/random/Scarb.lock b/crates/random/Scarb.lock new file mode 100644 index 00000000..37a223e0 --- /dev/null +++ b/crates/random/Scarb.lock @@ -0,0 +1,6 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "origami_random" +version = "0.1.0" diff --git a/crates/random/Scarb.toml b/crates/random/Scarb.toml new file mode 100644 index 00000000..a36e319b --- /dev/null +++ b/crates/random/Scarb.toml @@ -0,0 +1,9 @@ +[package] +name = "origami_random" +version = "0.1.0" +description = "Random generator library for Dojo based games." +homepage = "https://github.com/dojoengine/origami/tree/main/crates/random" +edition = "2024_07" + +[dependencies] + diff --git a/crates/src/random/deck.cairo b/crates/random/src/deck.cairo similarity index 93% rename from crates/src/random/deck.cairo rename to crates/random/src/deck.cairo index 52dfa3aa..b907a2b8 100644 --- a/crates/src/random/deck.cairo +++ b/crates/random/src/deck.cairo @@ -2,10 +2,9 @@ // Core imports -use dict::{Felt252Dict, Felt252DictTrait}; -use hash::HashStateTrait; -use poseidon::PoseidonTrait; -use traits::{Into, Drop}; +use core::dict::{Felt252Dict, Felt252DictTrait}; +use core::hash::HashStateTrait; +use core::poseidon::PoseidonTrait; // Constants @@ -15,22 +14,22 @@ const MASK_1: u128 = 0x1; /// Deck struct. #[derive(Destruct)] -struct Deck { - seed: felt252, - keys: Felt252Dict, - cards: Felt252Dict, - remaining: u32, - nonce: u8, +pub struct Deck { + pub seed: felt252, + pub keys: Felt252Dict, + pub cards: Felt252Dict, + pub remaining: u32, + pub nonce: u8, } /// Errors module. -mod errors { - const NO_CARDS_LEFT: felt252 = 'Deck: no cards left'; - const TOO_MANY_CARDS: felt252 = 'Deck: too many cards'; +pub mod errors { + pub const NO_CARDS_LEFT: felt252 = 'Deck: no cards left'; + pub const TOO_MANY_CARDS: felt252 = 'Deck: too many cards'; } /// Trait to initialize, draw and discard a card from the Deck. -trait DeckTrait { +pub trait DeckTrait { /// Returns a new `Deck` struct. /// # Arguments /// * `seed` - A seed to initialize the deck. @@ -71,7 +70,7 @@ trait DeckTrait { } /// Implementation of the `DeckTrait` trait for the `Deck` struct. -impl DeckImpl of DeckTrait { +pub impl DeckImpl of DeckTrait { #[inline(always)] fn new(seed: felt252, number: u32) -> Deck { Deck { diff --git a/crates/src/random/dice.cairo b/crates/random/src/dice.cairo similarity index 90% rename from crates/src/random/dice.cairo rename to crates/random/src/dice.cairo index 2c5dab31..3c8fa6dd 100644 --- a/crates/src/random/dice.cairo +++ b/crates/random/src/dice.cairo @@ -2,20 +2,19 @@ // Core imports -use poseidon::PoseidonTrait; -use hash::HashStateTrait; -use traits::Into; +use core::poseidon::PoseidonTrait; +use core::hash::HashStateTrait; /// Dice struct. #[derive(Drop)] -struct Dice { - face_count: u8, - seed: felt252, - nonce: felt252, +pub struct Dice { + pub face_count: u8, + pub seed: felt252, + pub nonce: felt252, } /// Trait to initialize and roll a dice. -trait DiceTrait { +pub trait DiceTrait { /// Returns a new `Dice` struct. /// # Arguments /// * `face_count` - The number of faces. @@ -32,7 +31,7 @@ trait DiceTrait { } /// Implementation of the `DiceTrait` trait for the `Dice` struct. -impl DiceImpl of DiceTrait { +pub impl DiceImpl of DiceTrait { #[inline(always)] fn new(face_count: u8, seed: felt252) -> Dice { Dice { face_count, seed, nonce: 0 } diff --git a/crates/random/src/lib.cairo b/crates/random/src/lib.cairo new file mode 100644 index 00000000..54ab9226 --- /dev/null +++ b/crates/random/src/lib.cairo @@ -0,0 +1,2 @@ +pub mod deck; +pub mod dice; diff --git a/crates/rating/Scarb.toml b/crates/rating/Scarb.toml new file mode 100644 index 00000000..cbd18267 --- /dev/null +++ b/crates/rating/Scarb.toml @@ -0,0 +1,8 @@ +[package] +name = "origami_rating" +version = "0.1.0" +description = "Rating related algorithm library for Dojo based games." +homepage = "https://github.com/dojoengine/origami/tree/main/crates/rating" +edition = "2024_07" + +[dependencies] diff --git a/crates/src/rating/elo.cairo b/crates/rating/src/elo.cairo similarity index 94% rename from crates/src/rating/elo.cairo rename to crates/rating/src/elo.cairo index 814d1bbf..e5901404 100644 --- a/crates/src/rating/elo.cairo +++ b/crates/rating/src/elo.cairo @@ -2,9 +2,8 @@ //! Source: https://github.com/saucepoint/elo-lib/blob/main/src/Elo.sol // Core imports - -use core::integer::{u32_sqrt, u64_sqrt, u128_sqrt, u256_sqrt}; use core::integer::i128; +use core::num::traits::Sqrt; // Constants @@ -13,13 +12,13 @@ const SCALER: i128 = 800; // Errors -mod errors { - const ELO_DIFFERENCE_TOO_LARGE: felt252 = 'Elo: difference too large'; +pub mod errors { + pub const ELO_DIFFERENCE_TOO_LARGE: felt252 = 'Elo: difference too large'; } /// Elo implementation.. #[generate_trait] -impl EloImpl of EloTrait { +pub impl EloImpl of EloTrait { /// Calculates the change in ELO rating, after a given outcome. /// # Arguments /// * `rating_a` - The ELO rating of the player A. @@ -65,7 +64,9 @@ impl EloImpl of EloTrait { let order: u256 = order_felt.into() / 25; // [Info] Order should be less or equal to 77 to fit a u256 let powered: u256 = PrivateTrait::pow(10, order); - let rooted: u16 = u32_sqrt(u64_sqrt(u128_sqrt(u256_sqrt(powered)))); + let rooted: u16 = Sqrt::< + u32 + >::sqrt(Sqrt::::sqrt(Sqrt::::sqrt(Sqrt::::sqrt(powered)))); // [Compute] Change = k * (score - expectedScore) let k_expected_score = k.into() * MULTIPLIER / (100 + rooted.into()); diff --git a/crates/rating/src/lib.cairo b/crates/rating/src/lib.cairo new file mode 100644 index 00000000..217b18c4 --- /dev/null +++ b/crates/rating/src/lib.cairo @@ -0,0 +1 @@ +pub mod elo; diff --git a/crates/security/Scarb.lock b/crates/security/Scarb.lock new file mode 100644 index 00000000..7eacce55 --- /dev/null +++ b/crates/security/Scarb.lock @@ -0,0 +1,6 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "origami_security" +version = "0.1.0" diff --git a/crates/security/Scarb.toml b/crates/security/Scarb.toml new file mode 100644 index 00000000..f55b5715 --- /dev/null +++ b/crates/security/Scarb.toml @@ -0,0 +1,8 @@ +[package] +name = "origami_security" +version = "0.1.0" +description = "Security library for Dojo based games." +homepage = "https://github.com/dojoengine/origami/tree/main/crates/security" +edition = "2024_07" + +[dependencies] diff --git a/crates/src/security/commitment.cairo b/crates/security/src/commitment.cairo similarity index 81% rename from crates/src/security/commitment.cairo rename to crates/security/src/commitment.cairo index 134d17ae..02d49b74 100644 --- a/crates/src/security/commitment.cairo +++ b/crates/security/src/commitment.cairo @@ -1,22 +1,23 @@ -use poseidon::poseidon_hash_span; +use core::poseidon::poseidon_hash_span; +use core::num::traits::Zero; -#[derive(Copy, Drop, Default, Serde, dojo::Introspect)] -struct Commitment { - hash: felt252 +#[derive(Copy, Drop, Default, Serde)] +pub struct Commitment { + pub hash: felt252 } /// Errors module. -mod errors { - const COMMITMENT_INVALID_HASH: felt252 = 'Commitment: can not commit zero'; +pub mod errors { + pub const COMMITMENT_INVALID_HASH: felt252 = 'Commitment: can not commit zero'; } -trait CommitmentTrait { +pub trait CommitmentTrait { fn new() -> Commitment; fn commit(ref self: Commitment, hash: felt252); fn reveal, impl TDrop: Drop>(self: @Commitment, reveal: T) -> bool; } -impl CommitmentImpl of CommitmentTrait { +pub impl CommitmentImpl of CommitmentTrait { fn new() -> Commitment { Commitment { hash: 0 } } diff --git a/crates/security/src/lib.cairo b/crates/security/src/lib.cairo new file mode 100644 index 00000000..1f912381 --- /dev/null +++ b/crates/security/src/lib.cairo @@ -0,0 +1 @@ +pub mod commitment; diff --git a/crates/src/lib.cairo b/crates/src/lib.cairo deleted file mode 100644 index a0719f2c..00000000 --- a/crates/src/lib.cairo +++ /dev/null @@ -1,34 +0,0 @@ -mod algebra { - mod vec2; - mod vector; - mod matrix; -} - -mod defi { - mod auction { - mod gda; - mod vrgda; - mod helpers; - } -} - -mod rating { - mod elo; -} - - -mod random { - mod deck; - mod dice; -} - -mod security { - mod commitment; -} - -mod map { - mod hex { - mod hex; - mod types; - } -} diff --git a/token/.gitignore b/crates/token/.gitignore similarity index 100% rename from token/.gitignore rename to crates/token/.gitignore diff --git a/token/Scarb.lock b/crates/token/Scarb.lock similarity index 100% rename from token/Scarb.lock rename to crates/token/Scarb.lock diff --git a/crates/token/Scarb.toml b/crates/token/Scarb.toml new file mode 100644 index 00000000..d6d34ea4 --- /dev/null +++ b/crates/token/Scarb.toml @@ -0,0 +1,17 @@ +[package] +name = "origami_token" +version = "1.0.0-alpha.0" +description = "Implementations of ERC standards for the Dojo framework." +homepage = "https://github.com/dojoengine/origami/tree/crates/token" + +[dependencies] +dojo.workspace = true + +[lib] + +[[target.dojo]] + +[tool.dojo.world] +name = "token" +seed = "token" +namespace = { default = "origami_token" } diff --git a/token/scripts/genInterface.js b/crates/token/scripts/genInterface.js similarity index 100% rename from token/scripts/genInterface.js rename to crates/token/scripts/genInterface.js diff --git a/token/src/components/introspection/src5.cairo b/crates/token/src/components/introspection/src5.cairo similarity index 100% rename from token/src/components/introspection/src5.cairo rename to crates/token/src/components/introspection/src5.cairo diff --git a/token/src/components/security/initializable.cairo b/crates/token/src/components/security/initializable.cairo similarity index 100% rename from token/src/components/security/initializable.cairo rename to crates/token/src/components/security/initializable.cairo diff --git a/token/src/components/tests.cairo b/crates/token/src/components/tests.cairo similarity index 100% rename from token/src/components/tests.cairo rename to crates/token/src/components/tests.cairo diff --git a/token/src/components/tests/introspection/test_src5.cairo b/crates/token/src/components/tests/introspection/test_src5.cairo similarity index 100% rename from token/src/components/tests/introspection/test_src5.cairo rename to crates/token/src/components/tests/introspection/test_src5.cairo diff --git a/token/src/components/tests/mocks/erc20/erc20_allowance_mock.cairo b/crates/token/src/components/tests/mocks/erc20/erc20_allowance_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/erc20/erc20_allowance_mock.cairo rename to crates/token/src/components/tests/mocks/erc20/erc20_allowance_mock.cairo diff --git a/token/src/components/tests/mocks/erc20/erc20_balance_mock.cairo b/crates/token/src/components/tests/mocks/erc20/erc20_balance_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/erc20/erc20_balance_mock.cairo rename to crates/token/src/components/tests/mocks/erc20/erc20_balance_mock.cairo diff --git a/token/src/components/tests/mocks/erc20/erc20_bridgeable_mock.cairo b/crates/token/src/components/tests/mocks/erc20/erc20_bridgeable_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/erc20/erc20_bridgeable_mock.cairo rename to crates/token/src/components/tests/mocks/erc20/erc20_bridgeable_mock.cairo diff --git a/token/src/components/tests/mocks/erc20/erc20_metadata_mock.cairo b/crates/token/src/components/tests/mocks/erc20/erc20_metadata_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/erc20/erc20_metadata_mock.cairo rename to crates/token/src/components/tests/mocks/erc20/erc20_metadata_mock.cairo diff --git a/token/src/components/tests/mocks/erc20/erc20_mintable_burnable_mock.cairo b/crates/token/src/components/tests/mocks/erc20/erc20_mintable_burnable_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/erc20/erc20_mintable_burnable_mock.cairo rename to crates/token/src/components/tests/mocks/erc20/erc20_mintable_burnable_mock.cairo diff --git a/token/src/components/tests/mocks/erc721/erc721_approval_mock.cairo b/crates/token/src/components/tests/mocks/erc721/erc721_approval_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/erc721/erc721_approval_mock.cairo rename to crates/token/src/components/tests/mocks/erc721/erc721_approval_mock.cairo diff --git a/token/src/components/tests/mocks/erc721/erc721_balance_mock.cairo b/crates/token/src/components/tests/mocks/erc721/erc721_balance_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/erc721/erc721_balance_mock.cairo rename to crates/token/src/components/tests/mocks/erc721/erc721_balance_mock.cairo diff --git a/token/src/components/tests/mocks/erc721/erc721_enumerable_mock.cairo b/crates/token/src/components/tests/mocks/erc721/erc721_enumerable_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/erc721/erc721_enumerable_mock.cairo rename to crates/token/src/components/tests/mocks/erc721/erc721_enumerable_mock.cairo diff --git a/token/src/components/tests/mocks/erc721/erc721_metadata_mock.cairo b/crates/token/src/components/tests/mocks/erc721/erc721_metadata_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/erc721/erc721_metadata_mock.cairo rename to crates/token/src/components/tests/mocks/erc721/erc721_metadata_mock.cairo diff --git a/token/src/components/tests/mocks/erc721/erc721_mintable_burnable_mock.cairo b/crates/token/src/components/tests/mocks/erc721/erc721_mintable_burnable_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/erc721/erc721_mintable_burnable_mock.cairo rename to crates/token/src/components/tests/mocks/erc721/erc721_mintable_burnable_mock.cairo diff --git a/token/src/components/tests/mocks/erc721/erc721_receiver_mock.cairo b/crates/token/src/components/tests/mocks/erc721/erc721_receiver_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/erc721/erc721_receiver_mock.cairo rename to crates/token/src/components/tests/mocks/erc721/erc721_receiver_mock.cairo diff --git a/token/src/components/tests/mocks/initializable_mock.cairo b/crates/token/src/components/tests/mocks/initializable_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/initializable_mock.cairo rename to crates/token/src/components/tests/mocks/initializable_mock.cairo diff --git a/token/src/components/tests/mocks/src5_mock.cairo b/crates/token/src/components/tests/mocks/src5_mock.cairo similarity index 100% rename from token/src/components/tests/mocks/src5_mock.cairo rename to crates/token/src/components/tests/mocks/src5_mock.cairo diff --git a/token/src/components/tests/security/test_initializable.cairo b/crates/token/src/components/tests/security/test_initializable.cairo similarity index 100% rename from token/src/components/tests/security/test_initializable.cairo rename to crates/token/src/components/tests/security/test_initializable.cairo diff --git a/token/src/components/tests/token/erc20/test_erc20_allowance.cairo b/crates/token/src/components/tests/token/erc20/test_erc20_allowance.cairo similarity index 100% rename from token/src/components/tests/token/erc20/test_erc20_allowance.cairo rename to crates/token/src/components/tests/token/erc20/test_erc20_allowance.cairo diff --git a/token/src/components/tests/token/erc20/test_erc20_balance.cairo b/crates/token/src/components/tests/token/erc20/test_erc20_balance.cairo similarity index 100% rename from token/src/components/tests/token/erc20/test_erc20_balance.cairo rename to crates/token/src/components/tests/token/erc20/test_erc20_balance.cairo diff --git a/token/src/components/tests/token/erc20/test_erc20_bridgeable.cairo b/crates/token/src/components/tests/token/erc20/test_erc20_bridgeable.cairo similarity index 100% rename from token/src/components/tests/token/erc20/test_erc20_bridgeable.cairo rename to crates/token/src/components/tests/token/erc20/test_erc20_bridgeable.cairo diff --git a/token/src/components/tests/token/erc20/test_erc20_metadata.cairo b/crates/token/src/components/tests/token/erc20/test_erc20_metadata.cairo similarity index 100% rename from token/src/components/tests/token/erc20/test_erc20_metadata.cairo rename to crates/token/src/components/tests/token/erc20/test_erc20_metadata.cairo diff --git a/token/src/components/tests/token/erc20/test_erc20_mintable_burnable.cairo b/crates/token/src/components/tests/token/erc20/test_erc20_mintable_burnable.cairo similarity index 100% rename from token/src/components/tests/token/erc20/test_erc20_mintable_burnable.cairo rename to crates/token/src/components/tests/token/erc20/test_erc20_mintable_burnable.cairo diff --git a/token/src/components/tests/token/erc721/test_erc721_approval.cairo b/crates/token/src/components/tests/token/erc721/test_erc721_approval.cairo similarity index 100% rename from token/src/components/tests/token/erc721/test_erc721_approval.cairo rename to crates/token/src/components/tests/token/erc721/test_erc721_approval.cairo diff --git a/token/src/components/tests/token/erc721/test_erc721_balance.cairo b/crates/token/src/components/tests/token/erc721/test_erc721_balance.cairo similarity index 100% rename from token/src/components/tests/token/erc721/test_erc721_balance.cairo rename to crates/token/src/components/tests/token/erc721/test_erc721_balance.cairo diff --git a/token/src/components/tests/token/erc721/test_erc721_enumerable.cairo b/crates/token/src/components/tests/token/erc721/test_erc721_enumerable.cairo similarity index 100% rename from token/src/components/tests/token/erc721/test_erc721_enumerable.cairo rename to crates/token/src/components/tests/token/erc721/test_erc721_enumerable.cairo diff --git a/token/src/components/tests/token/erc721/test_erc721_metadata.cairo b/crates/token/src/components/tests/token/erc721/test_erc721_metadata.cairo similarity index 100% rename from token/src/components/tests/token/erc721/test_erc721_metadata.cairo rename to crates/token/src/components/tests/token/erc721/test_erc721_metadata.cairo diff --git a/token/src/components/tests/token/erc721/test_erc721_mintable_burnable.cairo b/crates/token/src/components/tests/token/erc721/test_erc721_mintable_burnable.cairo similarity index 100% rename from token/src/components/tests/token/erc721/test_erc721_mintable_burnable.cairo rename to crates/token/src/components/tests/token/erc721/test_erc721_mintable_burnable.cairo diff --git a/token/src/components/token/erc20/erc20_allowance.cairo b/crates/token/src/components/token/erc20/erc20_allowance.cairo similarity index 100% rename from token/src/components/token/erc20/erc20_allowance.cairo rename to crates/token/src/components/token/erc20/erc20_allowance.cairo diff --git a/token/src/components/token/erc20/erc20_balance.cairo b/crates/token/src/components/token/erc20/erc20_balance.cairo similarity index 100% rename from token/src/components/token/erc20/erc20_balance.cairo rename to crates/token/src/components/token/erc20/erc20_balance.cairo diff --git a/token/src/components/token/erc20/erc20_bridgeable.cairo b/crates/token/src/components/token/erc20/erc20_bridgeable.cairo similarity index 100% rename from token/src/components/token/erc20/erc20_bridgeable.cairo rename to crates/token/src/components/token/erc20/erc20_bridgeable.cairo diff --git a/token/src/components/token/erc20/erc20_burnable.cairo b/crates/token/src/components/token/erc20/erc20_burnable.cairo similarity index 100% rename from token/src/components/token/erc20/erc20_burnable.cairo rename to crates/token/src/components/token/erc20/erc20_burnable.cairo diff --git a/token/src/components/token/erc20/erc20_metadata.cairo b/crates/token/src/components/token/erc20/erc20_metadata.cairo similarity index 100% rename from token/src/components/token/erc20/erc20_metadata.cairo rename to crates/token/src/components/token/erc20/erc20_metadata.cairo diff --git a/token/src/components/token/erc20/erc20_mintable.cairo b/crates/token/src/components/token/erc20/erc20_mintable.cairo similarity index 100% rename from token/src/components/token/erc20/erc20_mintable.cairo rename to crates/token/src/components/token/erc20/erc20_mintable.cairo diff --git a/token/src/components/token/erc721/erc721_approval.cairo b/crates/token/src/components/token/erc721/erc721_approval.cairo similarity index 100% rename from token/src/components/token/erc721/erc721_approval.cairo rename to crates/token/src/components/token/erc721/erc721_approval.cairo diff --git a/token/src/components/token/erc721/erc721_balance.cairo b/crates/token/src/components/token/erc721/erc721_balance.cairo similarity index 100% rename from token/src/components/token/erc721/erc721_balance.cairo rename to crates/token/src/components/token/erc721/erc721_balance.cairo diff --git a/token/src/components/token/erc721/erc721_burnable.cairo b/crates/token/src/components/token/erc721/erc721_burnable.cairo similarity index 100% rename from token/src/components/token/erc721/erc721_burnable.cairo rename to crates/token/src/components/token/erc721/erc721_burnable.cairo diff --git a/token/src/components/token/erc721/erc721_enumerable.cairo b/crates/token/src/components/token/erc721/erc721_enumerable.cairo similarity index 100% rename from token/src/components/token/erc721/erc721_enumerable.cairo rename to crates/token/src/components/token/erc721/erc721_enumerable.cairo diff --git a/token/src/components/token/erc721/erc721_metadata.cairo b/crates/token/src/components/token/erc721/erc721_metadata.cairo similarity index 100% rename from token/src/components/token/erc721/erc721_metadata.cairo rename to crates/token/src/components/token/erc721/erc721_metadata.cairo diff --git a/token/src/components/token/erc721/erc721_mintable.cairo b/crates/token/src/components/token/erc721/erc721_mintable.cairo similarity index 100% rename from token/src/components/token/erc721/erc721_mintable.cairo rename to crates/token/src/components/token/erc721/erc721_mintable.cairo diff --git a/token/src/components/token/erc721/erc721_owner.cairo b/crates/token/src/components/token/erc721/erc721_owner.cairo similarity index 100% rename from token/src/components/token/erc721/erc721_owner.cairo rename to crates/token/src/components/token/erc721/erc721_owner.cairo diff --git a/token/src/components/token/erc721/erc721_receiver.cairo b/crates/token/src/components/token/erc721/erc721_receiver.cairo similarity index 100% rename from token/src/components/token/erc721/erc721_receiver.cairo rename to crates/token/src/components/token/erc721/erc721_receiver.cairo diff --git a/token/src/components/token/erc721/interface.cairo b/crates/token/src/components/token/erc721/interface.cairo similarity index 100% rename from token/src/components/token/erc721/interface.cairo rename to crates/token/src/components/token/erc721/interface.cairo diff --git a/token/src/erc1155/erc1155.cairo b/crates/token/src/erc1155/erc1155.cairo similarity index 100% rename from token/src/erc1155/erc1155.cairo rename to crates/token/src/erc1155/erc1155.cairo diff --git a/token/src/erc1155/interface.cairo b/crates/token/src/erc1155/interface.cairo similarity index 100% rename from token/src/erc1155/interface.cairo rename to crates/token/src/erc1155/interface.cairo diff --git a/token/src/erc1155/models.cairo b/crates/token/src/erc1155/models.cairo similarity index 100% rename from token/src/erc1155/models.cairo rename to crates/token/src/erc1155/models.cairo diff --git a/token/src/erc1155/tests.cairo b/crates/token/src/erc1155/tests.cairo similarity index 100% rename from token/src/erc1155/tests.cairo rename to crates/token/src/erc1155/tests.cairo diff --git a/token/src/erc20/erc20.cairo b/crates/token/src/erc20/erc20.cairo similarity index 100% rename from token/src/erc20/erc20.cairo rename to crates/token/src/erc20/erc20.cairo diff --git a/token/src/erc20/interface.cairo b/crates/token/src/erc20/interface.cairo similarity index 100% rename from token/src/erc20/interface.cairo rename to crates/token/src/erc20/interface.cairo diff --git a/token/src/erc20/models.cairo b/crates/token/src/erc20/models.cairo similarity index 100% rename from token/src/erc20/models.cairo rename to crates/token/src/erc20/models.cairo diff --git a/token/src/erc20/tests.cairo b/crates/token/src/erc20/tests.cairo similarity index 100% rename from token/src/erc20/tests.cairo rename to crates/token/src/erc20/tests.cairo diff --git a/token/src/erc721/erc721.cairo b/crates/token/src/erc721/erc721.cairo similarity index 100% rename from token/src/erc721/erc721.cairo rename to crates/token/src/erc721/erc721.cairo diff --git a/token/src/erc721/interface.cairo b/crates/token/src/erc721/interface.cairo similarity index 100% rename from token/src/erc721/interface.cairo rename to crates/token/src/erc721/interface.cairo diff --git a/token/src/erc721/models.cairo b/crates/token/src/erc721/models.cairo similarity index 100% rename from token/src/erc721/models.cairo rename to crates/token/src/erc721/models.cairo diff --git a/token/src/erc721/tests.cairo b/crates/token/src/erc721/tests.cairo similarity index 100% rename from token/src/erc721/tests.cairo rename to crates/token/src/erc721/tests.cairo diff --git a/token/src/lib.cairo b/crates/token/src/lib.cairo similarity index 100% rename from token/src/lib.cairo rename to crates/token/src/lib.cairo diff --git a/token/src/presets/erc20/bridgeable.cairo b/crates/token/src/presets/erc20/bridgeable.cairo similarity index 100% rename from token/src/presets/erc20/bridgeable.cairo rename to crates/token/src/presets/erc20/bridgeable.cairo diff --git a/token/src/presets/erc20/tests_bridgeable.cairo b/crates/token/src/presets/erc20/tests_bridgeable.cairo similarity index 100% rename from token/src/presets/erc20/tests_bridgeable.cairo rename to crates/token/src/presets/erc20/tests_bridgeable.cairo diff --git a/token/src/presets/erc721/enumerable_mintable_burnable.cairo b/crates/token/src/presets/erc721/enumerable_mintable_burnable.cairo similarity index 100% rename from token/src/presets/erc721/enumerable_mintable_burnable.cairo rename to crates/token/src/presets/erc721/enumerable_mintable_burnable.cairo diff --git a/token/src/presets/erc721/mintable_burnable.cairo b/crates/token/src/presets/erc721/mintable_burnable.cairo similarity index 100% rename from token/src/presets/erc721/mintable_burnable.cairo rename to crates/token/src/presets/erc721/mintable_burnable.cairo diff --git a/token/src/presets/erc721/tests_enumerable_mintable_burnable.cairo b/crates/token/src/presets/erc721/tests_enumerable_mintable_burnable.cairo similarity index 100% rename from token/src/presets/erc721/tests_enumerable_mintable_burnable.cairo rename to crates/token/src/presets/erc721/tests_enumerable_mintable_burnable.cairo diff --git a/token/src/presets/erc721/tests_mintable_burnable.cairo b/crates/token/src/presets/erc721/tests_mintable_burnable.cairo similarity index 100% rename from token/src/presets/erc721/tests_mintable_burnable.cairo rename to crates/token/src/presets/erc721/tests_mintable_burnable.cairo diff --git a/token/src/tests/constants.cairo b/crates/token/src/tests/constants.cairo similarity index 100% rename from token/src/tests/constants.cairo rename to crates/token/src/tests/constants.cairo diff --git a/token/src/tests/utils.cairo b/crates/token/src/tests/utils.cairo similarity index 100% rename from token/src/tests/utils.cairo rename to crates/token/src/tests/utils.cairo diff --git a/examples/bridge/DEPLOYMENT.md b/examples/bridge/DEPLOYMENT.md deleted file mode 100644 index f6e6561f..00000000 --- a/examples/bridge/DEPLOYMENT.md +++ /dev/null @@ -1,41 +0,0 @@ -in /l1 & /sn Makefile, import the right .env -use `make` without argument to check current env vars - -## L1 - -- set STARKNET_ADDRESS (for goerli & mainnet) -- set TOKEN_ADDRESS (for mainnet) -- Pre-compute L1DojoBridge address with create3 - -## Starknet - -- set L1_BRIDGE_ADDRESS in sn/ .env -- Deploy contracts -- Set auth -- Initialize contracts - -## L1 - -- set L2_BRIDGE_ADDRESS in l1/ .env -- Deploy L1DojoBridge - - - -## Constructor / initiliazers - -### L1 -L1DojoBridge constructor : - -`constructor(address _starknet, address _l1Token, uint256 _l2Bridge)` - -### SN - -dojo_bridge initializer : - -`fn initializer(ref self: ContractState, l1_bridge: felt252, l2_token: ContractAddress)` - -dojo_token initializer : - -`fn initializer(ref self: ContractState, name: felt252, symbol: felt252, l2_bridge_address: ContractAddress)` - - diff --git a/examples/bridge/DEVELOPMENT.md b/examples/bridge/DEVELOPMENT.md deleted file mode 100644 index 94aa9082..00000000 --- a/examples/bridge/DEVELOPMENT.md +++ /dev/null @@ -1,89 +0,0 @@ -For local use -Make sure both Makefiles use .env.local -You can just use `make` without argument to check current env vars - -# ETH - -### Terminal 1 - -Launch anvil - -```sh -cd l1 -make anvil -``` - -### Terminal 2 - -Deploy create3 contract for deterministic contract address -```sh -cd l1 -make create3 -``` - -Deploy eth $TOKEN & L1DojoBridge -```sh -make deploy -``` - -# Starknet - -### Terminal 1 - -Launch katana with messaging - -```sh -cd sn -make katana_msg -# or -katana --messaging anvil.messaging.json -``` - -### Terminal 2 - -Migrate & initialize contracts -```sh -cd sn -make migrate_and_init -# or -make migrate -make initialize -``` - -Fund an address in ETH -```sh -./scripts/fund.sh 0x1234 -``` - -# Bridging - -## from ETH to Starknet - -it mint tokens & approve bridge & call deposit on ETH bridge -```sh -make deposit -``` - -## from Starknet to ETH - -get balance on Starknet -```sh -scarb run get_balance -``` - -withdraw from Starknet to ETH -```sh -scarb run withdraw -``` - -## after - -withdraw tokens from ETH bridge -```sh -make withdraw -``` - -check token balance on ETH -```sh -make get_balance -``` \ No newline at end of file diff --git a/examples/bridge/README.md b/examples/bridge/README.md deleted file mode 100644 index ff0b6652..00000000 --- a/examples/bridge/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## DOJO BRIDGE - -Adaptation of https://github.com/BibliothecaDAO/Starknet-ERC20-bridge & https://github.com/glihm/starknet-messaging-dev for Dojo. - - -## Requirements - -Please before starting, install: - -- [scarb](https://docs.swmansion.com/scarb/) to build cairo contracts. -- [starkli](https://github.com/xJonathanLEI/starkli) to interact with Katana. -- [foundry](https://book.getfoundry.sh/getting-started/installation) to interact with Anvil. -- git submodules forge-std & create3-factory. - diff --git a/examples/bridge/l1/.env.local b/examples/bridge/l1/.env.local deleted file mode 100644 index c4a405f5..00000000 --- a/examples/bridge/l1/.env.local +++ /dev/null @@ -1,13 +0,0 @@ -ENV=local - -ETH_RPC_URL=http://127.0.0.1:8545 - -ACCOUNT_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -ACCOUNT_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 - -# local -CREATE3_FACTORY_ADDRESS=0x5FbDB2315678afecb367f032d93F642f64180aa3 -STARKNET_ADDRESS=0x0000000000000000000000000000000000000000 -TOKEN_ADDRESS=0x0000000000000000000000000000000000000000 - -L2_BRIDGE_ADDRESS=0x2ff2f9994ba7e039f50190cb3b3dc538d9abf7201acbe5a6a7aff686dd40d89 diff --git a/examples/bridge/l1/.gitignore b/examples/bridge/l1/.gitignore deleted file mode 100644 index cbd1128e..00000000 --- a/examples/bridge/l1/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# Dotenv file -.env - -# Compiler files -cache/ -out/ -broadcast/ - - -lib/forge-std - -/logs - -.gas-snapshot \ No newline at end of file diff --git a/examples/bridge/l1/Makefile b/examples/bridge/l1/Makefile deleted file mode 100644 index 7c25d69a..00000000 --- a/examples/bridge/l1/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -include .env.local - -export - -PARAMS := --broadcast --rpc-url ${ETH_RPC_URL} -v - -all: - @echo "********************************************************************" - @echo "ENV : ${ENV}" - @echo "********************************************************************" - @echo "ETH_RPC_URL : ${ETH_RPC_URL}" - @echo "ACCOUNT_ADDRESS : ${ACCOUNT_ADDRESS}" - @echo "CREATE3_FACTORY_ADDRESS : ${CREATE3_FACTORY_ADDRESS}" - @echo "STARKNET_ADDRESS : ${STARKNET_ADDRESS}" - @echo "TOKEN_ADDRESSS : ${TOKEN_ADDRESSS}" - @echo "L2_BRIDGE_ADDRESS : ${L2_BRIDGE_ADDRESS}" - @echo "********************************************************************" - -anvil: - anvil --chain-id 1337 - -anvil_slow: - anvil --chain-id 1337 --block-time 10 - -create3: - forge script ./script/Deploy.s.sol:Create3 ${PARAMS} - -get_bridge_address: - forge script ./script/Deploy.s.sol:GetBridgeAddress ${PARAMS} - -deploy: - forge script ./script/Deploy.s.sol:Deploy ${PARAMS} - -deposit: - forge script ./script/Calls.s.sol:Deposit ${PARAMS} - -withdraw: - forge script ./script/Calls.s.sol:Withdraw ${PARAMS} - -get_balance: - forge script ./script/Calls.s.sol:GetBalance ${PARAMS} - -mint_token: - forge script ./script/Calls.s.sol:MintToken ${PARAMS} \ No newline at end of file diff --git a/examples/bridge/l1/foundry.toml b/examples/bridge/l1/foundry.toml deleted file mode 100644 index fbe80ee9..00000000 --- a/examples/bridge/l1/foundry.toml +++ /dev/null @@ -1,20 +0,0 @@ -[profile.default] -solc-version = "0.8.13" -src = "src" -out = "out" -libs = ["lib"] -fs_permissions = [{ access = "read-write", path = "./logs"}] -remappings = [ - "@forge-std/=lib/forge-std/src/", - "@create3-factory/=lib/create3-factory/src/", - "@openzeppelin/=lib/@openzeppelin/", - "@starknet/=lib/starknet/", -] - -# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options - - -# since the foundry.toml is commited it's not recommened to have the api key explicitly -# [rpc_endpoints] -# local = "${ETH_RPC_URL}" - diff --git a/examples/bridge/l1/lib/@openzeppelin/contracts/access/Ownable.sol b/examples/bridge/l1/lib/@openzeppelin/contracts/access/Ownable.sol deleted file mode 100644 index 16469d5a..00000000 --- a/examples/bridge/l1/lib/@openzeppelin/contracts/access/Ownable.sol +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -import "../utils/Context.sol"; - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _setOwner(_msgSender()); - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - _; - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _setOwner(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _setOwner(newOwner); - } - - function _setOwner(address newOwner) private { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} diff --git a/examples/bridge/l1/lib/@openzeppelin/contracts/token/ERC20/ERC20.sol b/examples/bridge/l1/lib/@openzeppelin/contracts/token/ERC20/ERC20.sol deleted file mode 100644 index 46122eb0..00000000 --- a/examples/bridge/l1/lib/@openzeppelin/contracts/token/ERC20/ERC20.sol +++ /dev/null @@ -1,355 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -import "./IERC20.sol"; -import "./extensions/IERC20Metadata.sol"; -import "../../utils/Context.sol"; - -/** - * @dev Implementation of the {IERC20} interface. - * - * This implementation is agnostic to the way tokens are created. This means - * that a supply mechanism has to be added in a derived contract using {_mint}. - * For a generic mechanism see {ERC20PresetMinterPauser}. - * - * TIP: For a detailed writeup see our guide - * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How - * to implement supply mechanisms]. - * - * We have followed general OpenZeppelin Contracts guidelines: functions revert - * instead returning `false` on failure. This behavior is nonetheless - * conventional and does not conflict with the expectations of ERC20 - * applications. - * - * Additionally, an {Approval} event is emitted on calls to {transferFrom}. - * This allows applications to reconstruct the allowance for all accounts just - * by listening to said events. Other implementations of the EIP may not emit - * these events, as it isn't required by the specification. - * - * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} - * functions have been added to mitigate the well-known issues around setting - * allowances. See {IERC20-approve}. - */ -contract ERC20 is Context, IERC20, IERC20Metadata { - mapping(address => uint256) private _balances; - - mapping(address => mapping(address => uint256)) private _allowances; - - uint256 private _totalSupply; - - string private _name; - string private _symbol; - - /** - * @dev Sets the values for {name} and {symbol}. - * - * The default value of {decimals} is 18. To select a different value for - * {decimals} you should overload it. - * - * All two of these values are immutable: they can only be set once during - * construction. - */ - constructor(string memory name_, string memory symbol_) { - _name = name_; - _symbol = symbol_; - } - - /** - * @dev Returns the name of the token. - */ - function name() public view virtual override returns (string memory) { - return _name; - } - - /** - * @dev Returns the symbol of the token, usually a shorter version of the - * name. - */ - function symbol() public view virtual override returns (string memory) { - return _symbol; - } - - /** - * @dev Returns the number of decimals used to get its user representation. - * For example, if `decimals` equals `2`, a balance of `505` tokens should - * be displayed to a user as `5.05` (`505 / 10 ** 2`). - * - * Tokens usually opt for a value of 18, imitating the relationship between - * Ether and Wei. This is the value {ERC20} uses, unless this function is - * overridden; - * - * NOTE: This information is only used for _display_ purposes: it in - * no way affects any of the arithmetic of the contract, including - * {IERC20-balanceOf} and {IERC20-transfer}. - */ - function decimals() public view virtual override returns (uint8) { - return 18; - } - - /** - * @dev See {IERC20-totalSupply}. - */ - function totalSupply() public view virtual override returns (uint256) { - return _totalSupply; - } - - /** - * @dev See {IERC20-balanceOf}. - */ - function balanceOf(address account) public view virtual override returns (uint256) { - return _balances[account]; - } - - /** - * @dev See {IERC20-transfer}. - * - * Requirements: - * - * - `recipient` cannot be the zero address. - * - the caller must have a balance of at least `amount`. - */ - function transfer(address recipient, uint256 amount) public virtual override returns (bool) { - _transfer(_msgSender(), recipient, amount); - return true; - } - - /** - * @dev See {IERC20-allowance}. - */ - function allowance(address owner, address spender) public view virtual override returns (uint256) { - return _allowances[owner][spender]; - } - - /** - * @dev See {IERC20-approve}. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function approve(address spender, uint256 amount) public virtual override returns (bool) { - _approve(_msgSender(), spender, amount); - return true; - } - - /** - * @dev See {IERC20-transferFrom}. - * - * Emits an {Approval} event indicating the updated allowance. This is not - * required by the EIP. See the note at the beginning of {ERC20}. - * - * Requirements: - * - * - `sender` and `recipient` cannot be the zero address. - * - `sender` must have a balance of at least `amount`. - * - the caller must have allowance for ``sender``'s tokens of at least - * `amount`. - */ - function transferFrom( - address sender, - address recipient, - uint256 amount - ) public virtual override returns (bool) { - _transfer(sender, recipient, amount); - - uint256 currentAllowance = _allowances[sender][_msgSender()]; - require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); - unchecked { - _approve(sender, _msgSender(), currentAllowance - amount); - } - - return true; - } - - /** - * @dev Atomically increases the allowance granted to `spender` by the caller. - * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. - * - * Emits an {Approval} event indicating the updated allowance. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { - _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); - return true; - } - - /** - * @dev Atomically decreases the allowance granted to `spender` by the caller. - * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. - * - * Emits an {Approval} event indicating the updated allowance. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `spender` must have allowance for the caller of at least - * `subtractedValue`. - */ - function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { - uint256 currentAllowance = _allowances[_msgSender()][spender]; - require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); - unchecked { - _approve(_msgSender(), spender, currentAllowance - subtractedValue); - } - - return true; - } - - /** - * @dev Moves `amount` of tokens from `sender` to `recipient`. - * - * This internal function is equivalent to {transfer}, and can be used to - * e.g. implement automatic token fees, slashing mechanisms, etc. - * - * Emits a {Transfer} event. - * - * Requirements: - * - * - `sender` cannot be the zero address. - * - `recipient` cannot be the zero address. - * - `sender` must have a balance of at least `amount`. - */ - function _transfer( - address sender, - address recipient, - uint256 amount - ) internal virtual { - require(sender != address(0), "ERC20: transfer from the zero address"); - require(recipient != address(0), "ERC20: transfer to the zero address"); - - _beforeTokenTransfer(sender, recipient, amount); - - uint256 senderBalance = _balances[sender]; - require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); - unchecked { - _balances[sender] = senderBalance - amount; - } - _balances[recipient] += amount; - - emit Transfer(sender, recipient, amount); - - _afterTokenTransfer(sender, recipient, amount); - } - - /** @dev Creates `amount` tokens and assigns them to `account`, increasing - * the total supply. - * - * Emits a {Transfer} event with `from` set to the zero address. - * - * Requirements: - * - * - `account` cannot be the zero address. - */ - function _mint(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: mint to the zero address"); - - _beforeTokenTransfer(address(0), account, amount); - - _totalSupply += amount; - _balances[account] += amount; - emit Transfer(address(0), account, amount); - - _afterTokenTransfer(address(0), account, amount); - } - - /** - * @dev Destroys `amount` tokens from `account`, reducing the - * total supply. - * - * Emits a {Transfer} event with `to` set to the zero address. - * - * Requirements: - * - * - `account` cannot be the zero address. - * - `account` must have at least `amount` tokens. - */ - function _burn(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: burn from the zero address"); - - _beforeTokenTransfer(account, address(0), amount); - - uint256 accountBalance = _balances[account]; - require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); - unchecked { - _balances[account] = accountBalance - amount; - } - _totalSupply -= amount; - - emit Transfer(account, address(0), amount); - - _afterTokenTransfer(account, address(0), amount); - } - - /** - * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. - * - * This internal function is equivalent to `approve`, and can be used to - * e.g. set automatic allowances for certain subsystems, etc. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `owner` cannot be the zero address. - * - `spender` cannot be the zero address. - */ - function _approve( - address owner, - address spender, - uint256 amount - ) internal virtual { - require(owner != address(0), "ERC20: approve from the zero address"); - require(spender != address(0), "ERC20: approve to the zero address"); - - _allowances[owner][spender] = amount; - emit Approval(owner, spender, amount); - } - - /** - * @dev Hook that is called before any transfer of tokens. This includes - * minting and burning. - * - * Calling conditions: - * - * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens - * will be transferred to `to`. - * - when `from` is zero, `amount` tokens will be minted for `to`. - * - when `to` is zero, `amount` of ``from``'s tokens will be burned. - * - `from` and `to` are never both zero. - * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. - */ - function _beforeTokenTransfer( - address from, - address to, - uint256 amount - ) internal virtual {} - - /** - * @dev Hook that is called after any transfer of tokens. This includes - * minting and burning. - * - * Calling conditions: - * - * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens - * has been transferred to `to`. - * - when `from` is zero, `amount` tokens have been minted for `to`. - * - when `to` is zero, `amount` of ``from``'s tokens have been burned. - * - `from` and `to` are never both zero. - * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. - */ - function _afterTokenTransfer( - address from, - address to, - uint256 amount - ) internal virtual {} -} diff --git a/examples/bridge/l1/lib/@openzeppelin/contracts/token/ERC20/IERC20.sol b/examples/bridge/l1/lib/@openzeppelin/contracts/token/ERC20/IERC20.sol deleted file mode 100644 index 08a04ad7..00000000 --- a/examples/bridge/l1/lib/@openzeppelin/contracts/token/ERC20/IERC20.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address recipient, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `sender` to `recipient` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address sender, - address recipient, - uint256 amount - ) external returns (bool); - - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); -} diff --git a/examples/bridge/l1/lib/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol b/examples/bridge/l1/lib/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol deleted file mode 100644 index 4fb868ae..00000000 --- a/examples/bridge/l1/lib/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -import "../IERC20.sol"; - -/** - * @dev Interface for the optional metadata functions from the ERC20 standard. - * - * _Available since v4.1._ - */ -interface IERC20Metadata is IERC20 { - /** - * @dev Returns the name of the token. - */ - function name() external view returns (string memory); - - /** - * @dev Returns the symbol of the token. - */ - function symbol() external view returns (string memory); - - /** - * @dev Returns the decimals places of the token. - */ - function decimals() external view returns (uint8); -} diff --git a/examples/bridge/l1/lib/@openzeppelin/contracts/utils/Context.sol b/examples/bridge/l1/lib/@openzeppelin/contracts/utils/Context.sol deleted file mode 100644 index d03dc5f4..00000000 --- a/examples/bridge/l1/lib/@openzeppelin/contracts/utils/Context.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} diff --git a/examples/bridge/l1/lib/create3-factory b/examples/bridge/l1/lib/create3-factory deleted file mode 160000 index 0a42c507..00000000 --- a/examples/bridge/l1/lib/create3-factory +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0a42c5072ce05a19c8fc5d875e52963c5f16849e diff --git a/examples/bridge/l1/lib/starknet/IStarknetMessaging.sol b/examples/bridge/l1/lib/starknet/IStarknetMessaging.sol deleted file mode 100644 index b3ebea4b..00000000 --- a/examples/bridge/l1/lib/starknet/IStarknetMessaging.sol +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright 2019-2022 StarkWare Industries Ltd. - - Licensed under the Apache License, Version 2.0 (the "License"). - You may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.starkware.co/open-source-license/ - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions - and limitations under the License. -*/ -// SPDX-License-Identifier: Apache-2.0. -pragma solidity ^0.8.0; - -import "./IStarknetMessagingEvents.sol"; - -interface IStarknetMessaging is IStarknetMessagingEvents { - /** - Returns the max fee (in Wei) that StarkNet will accept per single message. - */ - function getMaxL1MsgFee() external pure returns (uint256); - - /** - Sends a message to an L2 contract. - This function is payable, the payed amount is the message fee. - - Returns the hash of the message and the nonce of the message. - */ - function sendMessageToL2( - uint256 toAddress, - uint256 selector, - uint256[] calldata payload - ) external payable returns (bytes32, uint256); - - /** - Consumes a message that was sent from an L2 contract. - - Returns the hash of the message. - */ - function consumeMessageFromL2(uint256 fromAddress, uint256[] calldata payload) - external - returns (bytes32); - - /** - Starts the cancellation of an L1 to L2 message. - A message can be canceled messageCancellationDelay() seconds after this function is called. - - Note: This function may only be called for a message that is currently pending and the caller - must be the sender of the that message. - */ - function startL1ToL2MessageCancellation( - uint256 toAddress, - uint256 selector, - uint256[] calldata payload, - uint256 nonce - ) external returns (bytes32); - - /** - Cancels an L1 to L2 message, this function should be called at least - messageCancellationDelay() seconds after the call to startL1ToL2MessageCancellation(). - A message may only be cancelled by its sender. - If the message is missing, the call will revert. - - Note that the message fee is not refunded. - */ - function cancelL1ToL2Message( - uint256 toAddress, - uint256 selector, - uint256[] calldata payload, - uint256 nonce - ) external returns (bytes32); -} diff --git a/examples/bridge/l1/lib/starknet/IStarknetMessagingEvents.sol b/examples/bridge/l1/lib/starknet/IStarknetMessagingEvents.sol deleted file mode 100644 index 11937727..00000000 --- a/examples/bridge/l1/lib/starknet/IStarknetMessagingEvents.sol +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright 2019-2022 StarkWare Industries Ltd. - - Licensed under the Apache License, Version 2.0 (the "License"). - You may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.starkware.co/open-source-license/ - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions - and limitations under the License. -*/ -// SPDX-License-Identifier: Apache-2.0. -pragma solidity ^0.8.0; - -interface IStarknetMessagingEvents { - // This event needs to be compatible with the one defined in Output.sol. - event LogMessageToL1(uint256 indexed fromAddress, address indexed toAddress, uint256[] payload); - - // An event that is raised when a message is sent from L1 to L2. - event LogMessageToL2( - address indexed fromAddress, - uint256 indexed toAddress, - uint256 indexed selector, - uint256[] payload, - uint256 nonce, - uint256 fee - ); - - // An event that is raised when a message from L2 to L1 is consumed. - event ConsumedMessageToL1( - uint256 indexed fromAddress, - address indexed toAddress, - uint256[] payload - ); - - // An event that is raised when a message from L1 to L2 is consumed. - event ConsumedMessageToL2( - address indexed fromAddress, - uint256 indexed toAddress, - uint256 indexed selector, - uint256[] payload, - uint256 nonce - ); - - // An event that is raised when a message from L1 to L2 Cancellation is started. - event MessageToL2CancellationStarted( - address indexed fromAddress, - uint256 indexed toAddress, - uint256 indexed selector, - uint256[] payload, - uint256 nonce - ); - - // An event that is raised when a message from L1 to L2 is canceled. - event MessageToL2Canceled( - address indexed fromAddress, - uint256 indexed toAddress, - uint256 indexed selector, - uint256[] payload, - uint256 nonce - ); -} diff --git a/examples/bridge/l1/lib/starknet/NamedStorage.sol b/examples/bridge/l1/lib/starknet/NamedStorage.sol deleted file mode 100644 index 5279f380..00000000 --- a/examples/bridge/l1/lib/starknet/NamedStorage.sol +++ /dev/null @@ -1,120 +0,0 @@ -/* - Copyright 2019-2022 StarkWare Industries Ltd. - - Licensed under the Apache License, Version 2.0 (the "License"). - You may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.starkware.co/open-source-license/ - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions - and limitations under the License. -*/ -// SPDX-License-Identifier: Apache-2.0. -pragma solidity ^0.8.0; - -/* - Library to provide basic storage, in storage location out of the low linear address space. - - New types of storage variables should be added here upon need. -*/ -library NamedStorage { - function bytes32ToUint256Mapping(string memory tag_) - internal - pure - returns (mapping(bytes32 => uint256) storage randomVariable) - { - bytes32 location = keccak256(abi.encodePacked(tag_)); - assembly { - randomVariable.slot := location - } - } - - function bytes32ToAddressMapping(string memory tag_) - internal - pure - returns (mapping(bytes32 => address) storage randomVariable) - { - bytes32 location = keccak256(abi.encodePacked(tag_)); - assembly { - randomVariable.slot := location - } - } - - function uintToAddressMapping(string memory tag_) - internal - pure - returns (mapping(uint256 => address) storage randomVariable) - { - bytes32 location = keccak256(abi.encodePacked(tag_)); - assembly { - randomVariable.slot := location - } - } - - function addressToBoolMapping(string memory tag_) - internal - pure - returns (mapping(address => bool) storage randomVariable) - { - bytes32 location = keccak256(abi.encodePacked(tag_)); - assembly { - randomVariable.slot := location - } - } - - function getUintValue(string memory tag_) internal view returns (uint256 retVal) { - bytes32 slot = keccak256(abi.encodePacked(tag_)); - assembly { - retVal := sload(slot) - } - } - - function setUintValue(string memory tag_, uint256 value) internal { - bytes32 slot = keccak256(abi.encodePacked(tag_)); - assembly { - sstore(slot, value) - } - } - - function setUintValueOnce(string memory tag_, uint256 value) internal { - require(getUintValue(tag_) == 0, "ALREADY_SET"); - setUintValue(tag_, value); - } - - function getAddressValue(string memory tag_) internal view returns (address retVal) { - bytes32 slot = keccak256(abi.encodePacked(tag_)); - assembly { - retVal := sload(slot) - } - } - - function setAddressValue(string memory tag_, address value) internal { - bytes32 slot = keccak256(abi.encodePacked(tag_)); - assembly { - sstore(slot, value) - } - } - - function setAddressValueOnce(string memory tag_, address value) internal { - require(getAddressValue(tag_) == address(0x0), "ALREADY_SET"); - setAddressValue(tag_, value); - } - - function getBoolValue(string memory tag_) internal view returns (bool retVal) { - bytes32 slot = keccak256(abi.encodePacked(tag_)); - assembly { - retVal := sload(slot) - } - } - - function setBoolValue(string memory tag_, bool value) internal { - bytes32 slot = keccak256(abi.encodePacked(tag_)); - assembly { - sstore(slot, value) - } - } -} diff --git a/examples/bridge/l1/lib/starknet/StarknetMessaging.sol b/examples/bridge/l1/lib/starknet/StarknetMessaging.sol deleted file mode 100644 index c8a1a63c..00000000 --- a/examples/bridge/l1/lib/starknet/StarknetMessaging.sol +++ /dev/null @@ -1,202 +0,0 @@ -/* - Copyright 2019-2022 StarkWare Industries Ltd. - - Licensed under the Apache License, Version 2.0 (the "License"). - You may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.starkware.co/open-source-license/ - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions - and limitations under the License. -*/ -// SPDX-License-Identifier: Apache-2.0. -pragma solidity ^0.8.0; - -import "./IStarknetMessaging.sol"; -import "./NamedStorage.sol"; - -/** - Implements sending messages to L2 by adding them to a pipe and consuming messages from L2 by - removing them from a different pipe. A deriving contract can handle the former pipe and add items - to the latter pipe while interacting with L2. -*/ -contract StarknetMessaging is IStarknetMessaging { - /* - Random slot storage elements and accessors. - */ - string constant L1L2_MESSAGE_MAP_TAG = "STARKNET_1.0_MSGING_L1TOL2_MAPPPING_V2"; - string constant L2L1_MESSAGE_MAP_TAG = "STARKNET_1.0_MSGING_L2TOL1_MAPPPING"; - - string constant L1L2_MESSAGE_NONCE_TAG = "STARKNET_1.0_MSGING_L1TOL2_NONCE"; - - string constant L1L2_MESSAGE_CANCELLATION_MAP_TAG = ( - "STARKNET_1.0_MSGING_L1TOL2_CANCELLATION_MAPPPING" - ); - - string constant L1L2_MESSAGE_CANCELLATION_DELAY_TAG = ( - "STARKNET_1.0_MSGING_L1TOL2_CANCELLATION_DELAY" - ); - - uint256 constant MAX_L1_MSG_FEE = 1 ether; - - function getMaxL1MsgFee() public pure override returns (uint256) { - return MAX_L1_MSG_FEE; - } - - /** - Returns the msg_fee + 1 for the message with the given 'msgHash', - or 0 if no message with such a hash is pending. - */ - function l1ToL2Messages(bytes32 msgHash) external view returns (uint256) { - return l1ToL2Messages()[msgHash]; - } - - function l2ToL1Messages(bytes32 msgHash) external view returns (uint256) { - return l2ToL1Messages()[msgHash]; - } - - function l1ToL2Messages() internal pure returns (mapping(bytes32 => uint256) storage) { - return NamedStorage.bytes32ToUint256Mapping(L1L2_MESSAGE_MAP_TAG); - } - - function l2ToL1Messages() internal pure returns (mapping(bytes32 => uint256) storage) { - return NamedStorage.bytes32ToUint256Mapping(L2L1_MESSAGE_MAP_TAG); - } - - function l1ToL2MessageNonce() public view returns (uint256) { - return NamedStorage.getUintValue(L1L2_MESSAGE_NONCE_TAG); - } - - function messageCancellationDelay() public view returns (uint256) { - return NamedStorage.getUintValue(L1L2_MESSAGE_CANCELLATION_DELAY_TAG); - } - - function messageCancellationDelay(uint256 delayInSeconds) internal { - NamedStorage.setUintValue(L1L2_MESSAGE_CANCELLATION_DELAY_TAG, delayInSeconds); - } - - /** - Returns the timestamp at the time cancelL1ToL2Message was called with a message - matching 'msgHash'. - - The function returns 0 if cancelL1ToL2Message was never called. - */ - function l1ToL2MessageCancellations(bytes32 msgHash) external view returns (uint256) { - return l1ToL2MessageCancellations()[msgHash]; - } - - function l1ToL2MessageCancellations() - internal - pure - returns (mapping(bytes32 => uint256) storage) - { - return NamedStorage.bytes32ToUint256Mapping(L1L2_MESSAGE_CANCELLATION_MAP_TAG); - } - - /** - Returns the hash of an L1 -> L2 message from msg.sender. - */ - function getL1ToL2MsgHash( - uint256 toAddress, - uint256 selector, - uint256[] calldata payload, - uint256 nonce - ) internal view returns (bytes32) { - return - keccak256( - abi.encodePacked( - // MODIFIED HERE: adding uint160 for casting. - uint256(uint160(msg.sender)), - toAddress, - nonce, - selector, - payload.length, - payload - ) - ); - } - - /** - Sends a message to an L2 contract. - */ - function sendMessageToL2( - uint256 toAddress, - uint256 selector, - uint256[] calldata payload - ) external payable override returns (bytes32, uint256) { - require(msg.value > 0, "L1_MSG_FEE_MUST_BE_GREATER_THAN_0"); - require(msg.value <= getMaxL1MsgFee(), "MAX_L1_MSG_FEE_EXCEEDED"); - uint256 nonce = l1ToL2MessageNonce(); - NamedStorage.setUintValue(L1L2_MESSAGE_NONCE_TAG, nonce + 1); - emit LogMessageToL2(msg.sender, toAddress, selector, payload, nonce, msg.value); - bytes32 msgHash = getL1ToL2MsgHash(toAddress, selector, payload, nonce); - // Note that the inclusion of the unique nonce in the message hash implies that - // l1ToL2Messages()[msgHash] was not accessed before. - l1ToL2Messages()[msgHash] = msg.value + 1; - return (msgHash, nonce); - } - - /** - Consumes a message that was sent from an L2 contract. - - Returns the hash of the message. - */ - function consumeMessageFromL2(uint256 fromAddress, uint256[] calldata payload) - external - override - returns (bytes32) - { - bytes32 msgHash = keccak256( - // MODIFIED HERE: adding uint160 for casting. - abi.encodePacked(fromAddress, uint256(uint160(msg.sender)), payload.length, payload) - ); - - require(l2ToL1Messages()[msgHash] > 0, "INVALID_MESSAGE_TO_CONSUME"); - emit ConsumedMessageToL1(fromAddress, msg.sender, payload); - l2ToL1Messages()[msgHash] -= 1; - return msgHash; - } - - function startL1ToL2MessageCancellation( - uint256 toAddress, - uint256 selector, - uint256[] calldata payload, - uint256 nonce - ) external override returns (bytes32) { - emit MessageToL2CancellationStarted(msg.sender, toAddress, selector, payload, nonce); - bytes32 msgHash = getL1ToL2MsgHash(toAddress, selector, payload, nonce); - uint256 msgFeePlusOne = l1ToL2Messages()[msgHash]; - require(msgFeePlusOne > 0, "NO_MESSAGE_TO_CANCEL"); - l1ToL2MessageCancellations()[msgHash] = block.timestamp; - return msgHash; - } - - function cancelL1ToL2Message( - uint256 toAddress, - uint256 selector, - uint256[] calldata payload, - uint256 nonce - ) external override returns (bytes32) { - emit MessageToL2Canceled(msg.sender, toAddress, selector, payload, nonce); - // Note that the message hash depends on msg.sender, which prevents one contract from - // cancelling another contract's message. - // Trying to do so will result in NO_MESSAGE_TO_CANCEL. - bytes32 msgHash = getL1ToL2MsgHash(toAddress, selector, payload, nonce); - uint256 msgFeePlusOne = l1ToL2Messages()[msgHash]; - require(msgFeePlusOne != 0, "NO_MESSAGE_TO_CANCEL"); - - uint256 requestTime = l1ToL2MessageCancellations()[msgHash]; - require(requestTime != 0, "MESSAGE_CANCELLATION_NOT_REQUESTED"); - - uint256 cancelAllowedTime = requestTime + messageCancellationDelay(); - require(cancelAllowedTime >= requestTime, "CANCEL_ALLOWED_TIME_OVERFLOW"); - require(block.timestamp >= cancelAllowedTime, "MESSAGE_CANCELLATION_NOT_ALLOWED_YET"); - - l1ToL2Messages()[msgHash] = 0; - return (msgHash); - } -} diff --git a/examples/bridge/l1/script/BaseScript.sol b/examples/bridge/l1/script/BaseScript.sol deleted file mode 100644 index 16b8038f..00000000 --- a/examples/bridge/l1/script/BaseScript.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -import "forge-std/Script.sol"; -import "@create3-factory/CREATE3Factory.sol"; - -contract BaseScript is Script { - struct Env { - string ENV; - string ETH_RPC_URL; - uint256 ACCOUNT_PRIVATE_KEY; - address ACCOUNT_ADDRESS; - address CREATE3_FACTORY_ADDRESS; - address STARKNET_ADDRESS; - uint256 L2_BRIDGE_ADDRESS; - address TOKEN_ADDRESS; - } - - Env public env; - - constructor() { - loadEnv(); - } - - function getEnv() public view returns (Env memory ) { - return env; - } - - function loadEnv() public { - console.log("Loading Env..."); - - env.ENV = vm.envString("ENV"); - env.ETH_RPC_URL = vm.envString("ETH_RPC_URL"); - env.ACCOUNT_PRIVATE_KEY = vm.envUint("ACCOUNT_PRIVATE_KEY"); - env.ACCOUNT_ADDRESS = vm.envAddress("ACCOUNT_ADDRESS"); - env.CREATE3_FACTORY_ADDRESS = vm.envAddress("CREATE3_FACTORY_ADDRESS"); - env.STARKNET_ADDRESS = vm.envAddress("STARKNET_ADDRESS"); - env.L2_BRIDGE_ADDRESS = vm.envUint("L2_BRIDGE_ADDRESS"); - env.TOKEN_ADDRESS = vm.envAddress("TOKEN_ADDRESS"); - - console.log("ENV :", env.ENV); - console.log("ETH_RPC_URL :", env.ETH_RPC_URL); - - } - - function isLocal() public view returns (bool) { - return stringEquals(env.ENV, "local"); - } - - function isGoerli() public view returns (bool) { - return stringEquals(env.ENV, "goerli"); - } - - function stringEquals(string memory a, string memory b) public pure returns (bool) { - return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b)); - } -} diff --git a/examples/bridge/l1/script/Calls.s.sol b/examples/bridge/l1/script/Calls.s.sol deleted file mode 100644 index 7b279bb2..00000000 --- a/examples/bridge/l1/script/Calls.s.sol +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -import "forge-std/Script.sol"; - -import "../src/StarknetMessagingLocal.sol"; -import "../src/Token.sol"; -import "../src/L1DojoBridge.sol"; - -import "./BaseScript.sol"; - - -contract Deposit is BaseScript { - address _token; - address _L1DojoBridge; - - function setUp() public { - string memory json = vm.readFile('./logs/local.json'); - - _token = abi.decode(vm.parseJson(json,'.Token'), (address)); - _L1DojoBridge = abi.decode(vm.parseJson(json,'.L1DojoBridge'), (address)); - } - - function run() public{ - vm.startBroadcast(this.getEnv().ACCOUNT_PRIVATE_KEY); - - uint256 amount = 1_000 * 10**18; - uint256 l2Recipient = 0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973; - uint fee = 30_000; - - // mint token to owner - Token(_token).mint(this.getEnv().ACCOUNT_ADDRESS, amount); - - // owner approve bridge for amount - Token(_token).approve(_L1DojoBridge, amount); - - // call token bridge - L1DojoBridge(_L1DojoBridge).deposit{value: fee}(amount, l2Recipient, fee); - - vm.stopBroadcast(); - } -} - - -contract Withdraw is BaseScript { - address _token; - address _L1DojoBridge; - - function setUp() public { - string memory json = vm.readFile('./logs/local.json'); - - _token = abi.decode(vm.parseJson(json,'.Token'), (address)); - _L1DojoBridge = abi.decode(vm.parseJson(json,'.L1DojoBridge'), (address)); - } - - function run() public returns(uint256 balance){ - vm.startBroadcast(this.getEnv().ACCOUNT_PRIVATE_KEY); - - uint256 amount = 1_000 * 10**18; - address l1Recipient = this.getEnv().ACCOUNT_ADDRESS; - uint256 l2TxHash = 0; - - - // call token bridge - L1DojoBridge(_L1DojoBridge).withdraw(amount, l1Recipient, l2TxHash); - - // get balance - balance = Token(_token).balanceOf(l1Recipient); - - vm.stopBroadcast(); - } -} - -contract GetBalance is BaseScript { - address _token; - - function setUp() public { - string memory json = vm.readFile('./logs/local.json'); - _token = abi.decode(vm.parseJson(json,'.Token'), (address)); - } - - function run() public returns(uint256 balance){ - vm.startBroadcast(this.getEnv().ACCOUNT_PRIVATE_KEY); - - // get balance - balance = Token(_token).balanceOf(this.getEnv().ACCOUNT_ADDRESS); - - vm.stopBroadcast(); - } -} - - - -contract MintToken is BaseScript { - address _token; - - function setUp() public { - string memory json = vm.readFile('./logs/local.json'); - _token = abi.decode(vm.parseJson(json,'.Token'), (address)); - } - - function run() public{ - vm.startBroadcast(this.getEnv().ACCOUNT_PRIVATE_KEY); - - uint256 amount = 1_000 * 10**18; - // mint token to owner - Token(_token).mint(this.getEnv().ACCOUNT_ADDRESS, amount); - - vm.stopBroadcast(); - } -} diff --git a/examples/bridge/l1/script/Deploy.s.sol b/examples/bridge/l1/script/Deploy.s.sol deleted file mode 100644 index d478c948..00000000 --- a/examples/bridge/l1/script/Deploy.s.sol +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -import "forge-std/Script.sol"; -import "@create3-factory/CREATE3Factory.sol"; - -import "../src/StarknetMessagingLocal.sol"; -import "../src/Token.sol"; -import "../src/L1DojoBridge.sol"; -import "./BaseScript.sol"; - -bytes32 constant CREATE3_SALT = keccak256(bytes("CREATE3Salt")); - -bytes32 constant SN_SALT = keccak256(bytes("SNSalt")); -bytes32 constant TOKEN_SALT = keccak256(bytes("TokenSalt")); -bytes32 constant BRIDGE_SALT = keccak256(bytes("BridgeSalt")); - - -/** - Deploys the ContractMsg and StarknetMessagingLocal contracts. - Very handy to quickly setup Anvil to debug. -*/ -contract Deploy is BaseScript { - function setUp() public {} - - function run() public { - CREATE3Factory factory = CREATE3Factory( - this.getEnv().CREATE3_FACTORY_ADDRESS - ); - - string memory json = ""; - - vm.startBroadcast(this.getEnv().ACCOUNT_PRIVATE_KEY); - - address starknetAddress; - if (this.isLocal()) { - starknetAddress = address(new StarknetMessagingLocal()); - } else { - starknetAddress = this.getEnv().STARKNET_ADDRESS; - } - vm.serializeString( - json, - "StarknetAddress", - vm.toString(starknetAddress) - ); - - address tokenAddress; - - if (this.isLocal() /*|| this.isGoerli()*/) { - tokenAddress = address(new Token()); - } else { - tokenAddress = this.getEnv().TOKEN_ADDRESS; - } - vm.serializeString(json, "Token", vm.toString(tokenAddress)); - - address l1DojoBridge = factory.deploy( - BRIDGE_SALT, - abi.encodePacked( - type(L1DojoBridge).creationCode, - abi.encode( - starknetAddress, - tokenAddress, - this.getEnv().L2_BRIDGE_ADDRESS - ) - ) - ); - vm.serializeString(json, "L1DojoBridge", vm.toString(l1DojoBridge)); - - vm.stopBroadcast(); - - string memory data = vm.serializeBool(json, "success", true); - - string memory localLogs = "./logs/"; - vm.createDir(localLogs, true); - vm.writeJson( - data, - string.concat(localLogs, this.getEnv().ENV, ".json") - ); - } -} - -contract GetBridgeAddress is BaseScript { - function setUp() public {} - - function run() public returns (address bridgeAddress) { - CREATE3Factory factory = CREATE3Factory( - this.getEnv().CREATE3_FACTORY_ADDRESS - ); - - vm.startBroadcast(this.getEnv().ACCOUNT_PRIVATE_KEY); - - bridgeAddress = factory.getDeployed( - this.getEnv().ACCOUNT_ADDRESS, - BRIDGE_SALT - ); - - vm.stopBroadcast(); - } -} - -contract Create3 is BaseScript { - function setUp() public {} - - function run() public returns (address) { - if (this.isLocal()) { - vm.startBroadcast(this.getEnv().ACCOUNT_PRIVATE_KEY); - CREATE3Factory factory = new CREATE3Factory(); - return address(factory); - } else { - console.log( - "Already deployed on", - this.getEnv().ENV, - "at", - this.getEnv().CREATE3_FACTORY_ADDRESS - ); - return address(this.getEnv().CREATE3_FACTORY_ADDRESS); - } - } -} diff --git a/examples/bridge/l1/src/L1DojoBridge.sol b/examples/bridge/l1/src/L1DojoBridge.sol deleted file mode 100644 index 1067af92..00000000 --- a/examples/bridge/l1/src/L1DojoBridge.sol +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -interface IERC20Like { - function transfer(address to, uint256 amount) external returns (bool); - - function transferFrom( - address from, - address to, - uint256 value - ) external returns (bool success); -} - -interface IStarknetCore { - /** - Sends a message to an L2 contract. - - Returns the hash of the message. - */ - function sendMessageToL2( - uint256 toAddress, - uint256 selector, - uint256[] calldata payload - ) external payable returns (bytes32); - - /** - Consumes a message that was sent from an L2 contract. - - Returns the hash of the message. - */ - function consumeMessageFromL2( - uint256 fromAddress, - uint256[] calldata payload - ) external returns (bytes32); -} - -contract L1DojoBridge { - /// @notice The Starknet Core contract address on L1 - address public immutable starknet; - - /// @notice The $TOKEN ERC20 contract address on L1 - address public immutable l1Token; - - /// @notice The L2 address of the $TOKEN bridge, the counterpart to this contract - uint256 public immutable l2Bridge; - - event LogDeposit( - address indexed l1Sender, - uint256 amount, - uint256 l2Recipient - ); - event LogWithdrawal(address indexed l1Recipient, uint256 amount, uint256 l2TxHash); - - // 2 ** 251 + 17 * 2 ** 192 + 1; - uint256 private constant CAIRO_PRIME = - 3618502788666131213697322783095070105623107215331596699973092056135872020481; - - // from starkware.starknet.compiler.compile import get_selector_from_name - // print(get_selector_from_name('handle_deposit')) - uint256 private constant DEPOSIT_SELECTOR = - 1285101517810983806491589552491143496277809242732141897358598292095611420389; - - // operation ID sent in the L2 -> L1 message - uint256 private constant PROCESS_WITHDRAWAL = 1; - - function splitUint256( - uint256 value - ) internal pure returns (uint256, uint256) { - uint256 low = value & ((1 << 128) - 1); - uint256 high = value >> 128; - return (low, high); - } - - constructor(address _starknet, address _l1Token, uint256 _l2Bridge) { - require(_l2Bridge < CAIRO_PRIME, "Invalid L2 bridge address"); - - starknet = _starknet; - l1Token = _l1Token; - l2Bridge = _l2Bridge; - } - - /// @notice Function used to bridge $TOKEN from L1 to L2 - /// @param amount How many $TOKEN to send from msg.sender - /// @param l2Recipient To which L2 address should we deposit the $TOKEN to - /// @param fee Compulsory fee paid to the sequencer for passing on the message - function deposit( - uint256 amount, - uint256 l2Recipient, - uint256 fee - ) external payable { - require(amount > 0, "Amount is 0"); - require( - l2Recipient != 0 && - l2Recipient != l2Bridge && - l2Recipient < CAIRO_PRIME, - "Invalid L2 recipient" - ); - - uint256[] memory payload = new uint256[](3); - payload[0] = l2Recipient; - (payload[1], payload[2]) = splitUint256(amount); - - IERC20Like(l1Token).transferFrom(msg.sender, address(this), amount); - IStarknetCore(starknet).sendMessageToL2{value: fee}( - l2Bridge, - DEPOSIT_SELECTOR, - payload - ); - - emit LogDeposit(msg.sender, amount, l2Recipient); - } - - /// @notice Function to process the L2 withdrawal - /// @param amount How many $TOKEN were sent from L2 - /// @param l1Recipient Recipient of the (de)bridged $TOKEN - /// @param l2TxHash l2 tx_hash for matching txs in ui - function withdraw(uint256 amount, address l1Recipient, uint256 l2TxHash) external { - uint256[] memory payload = new uint256[](4); - payload[0] = PROCESS_WITHDRAWAL; - payload[1] = uint256(uint160(l1Recipient)); - (payload[2], payload[3]) = splitUint256(amount); - - // The call to consumeMessageFromL2 will succeed only if a - // matching L2->L1 message exists and is ready for consumption. - IStarknetCore(starknet).consumeMessageFromL2(l2Bridge, payload); - IERC20Like(l1Token).transfer(l1Recipient, amount); - - emit LogWithdrawal(l1Recipient, amount, l2TxHash); - } -} diff --git a/examples/bridge/l1/src/StarknetMessagingLocal.sol b/examples/bridge/l1/src/StarknetMessagingLocal.sol deleted file mode 100644 index 100d71f2..00000000 --- a/examples/bridge/l1/src/StarknetMessagingLocal.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0. -pragma solidity ^0.8.0; - -import "starknet/StarknetMessaging.sol"; - -/** - @notice Interface related to local messaging for Starknet. -*/ -interface IStarknetMessagingLocal { - function addMessageHashesFromL2( - uint256[] calldata msgHashes - ) - external - payable; -} - -/** - @title A superset of StarknetMessaging to support - local development by adding a way to directly register - a message hash ready to be consumed, without waiting the block - to be verified. - - @dev The idea is that, to not wait on the block to be proven, - this messaging contract can receive directly a hash of a message - to be considered as `received`. This message can then be consumed normally. - - DISCLAIMER: - The purpose of this contract is for local development only. -*/ -contract StarknetMessagingLocal is StarknetMessaging, IStarknetMessagingLocal { - - /** - @notice Hashes were added. - */ - event MessageHashesAddedFromL2( - uint256[] hashes - ); - - /** - @notice Adds the hashes of messages from L2. - - @param msgHashes Hashes to register as consumable. - */ - function addMessageHashesFromL2( - uint256[] calldata msgHashes - ) - external - payable - { - for (uint256 i = 0; i < msgHashes.length; i++) { - bytes32 hash = bytes32(msgHashes[i]); - l2ToL1Messages()[hash] += 1; - } - - emit MessageHashesAddedFromL2(msgHashes); - } - -} \ No newline at end of file diff --git a/examples/bridge/l1/src/Token.sol b/examples/bridge/l1/src/Token.sol deleted file mode 100644 index 4e34b69c..00000000 --- a/examples/bridge/l1/src/Token.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.2; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract Token is ERC20, Ownable { - constructor() ERC20("Token", "TOKEN") {} - - function mint(address to, uint256 amount) external onlyOwner { - _mint(to, amount); - } - - function faucet() external { - _mint(msg.sender, 1_000 ether); - } -} diff --git a/examples/bridge/l1/test/Token.sol b/examples/bridge/l1/test/Token.sol deleted file mode 100644 index 43048031..00000000 --- a/examples/bridge/l1/test/Token.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test, console2} from "forge-std/Test.sol"; -import {Token} from "../src/Token.sol"; - -contract TokenTest is Test { - Token public token; - - function setUp() public { - token = new Token(); - } - -} diff --git a/examples/bridge/sn/.env.local b/examples/bridge/sn/.env.local deleted file mode 100644 index 84c44c28..00000000 --- a/examples/bridge/sn/.env.local +++ /dev/null @@ -1,15 +0,0 @@ -ENV=local - -RPC_URL=http://localhost:5050 - - -ACCOUNT_ADDRESS=0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973 -ACCOUNT_PRIVATE_KEY=0x1800000000300000180000000000030000000000003006001800006600 - -L1_BRIDGE_ADDRESS=0x7966c7B8b78b563a2B01CC2172F64633fe5214dA - -DOJO_TOKEN_NAME=TOKEN -DOJO_TOKEN_SYMBOL=TOK - -WORLD_NAME=dojobridge - diff --git a/examples/bridge/sn/.gitignore b/examples/bridge/sn/.gitignore deleted file mode 100644 index 1a8f8c10..00000000 --- a/examples/bridge/sn/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.env -target - diff --git a/examples/bridge/sn/Makefile b/examples/bridge/sn/Makefile deleted file mode 100644 index efdc5e80..00000000 --- a/examples/bridge/sn/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -include .env.local - -export - -ifeq ($(origin KEYSTORE), undefined) - ACCOUNTS_PARAMS := --private-key ${ACCOUNT_PRIVATE_KEY} -else - ACCOUNTS_PARAMS := --keystore ${KEYSTORE} --password ${KEYSTORE_PASS} -endif - -PARAMS := --rpc-url ${RPC_URL} --account-address ${ACCOUNT_ADDRESS} ${ACCOUNTS_PARAMS} - -export SOZO_PARAMS = $(PARAMS) - -all: - @echo "********************************************************************" - @echo "ENV : ${ENV}" - @echo "WORLD_NAME : ${WORLD_NAME}" - @echo "********************************************************************" - @echo "RPC_URL : ${RPC_URL}" - @echo "ACCOUNT_ADDRESS : ${ACCOUNT_ADDRESS}" - @echo "KEYSTORE : ${KEYSTORE}" - @echo "ACCOUNT : ${ACCOUNT}" - @echo "********************************************************************" - @echo "L1_BRIDGE_ADDRESS : ${L1_BRIDGE_ADDRESS}" - @echo "DOJO_TOKEN_NAME : ${DOJO_TOKEN_NAME}" - @echo "DOJO_TOKEN_SYMBOL : ${DOJO_TOKEN_SYMBOL}" - @echo "********************************************************************" - - - -katana_msg: - katana --messaging anvil.messaging.json --dev - -katana_msg_slow: - katana --messaging anvil.messaging.json --dev --block-time 5000 - -build: - sozo build - -migrate: build - sozo migrate ${PARAMS} --name ${WORLD_NAME} --wait - -initialize: - ./scripts/initialize.sh - -migrate_and_init: migrate initialize - - - - diff --git a/examples/bridge/sn/Scarb.lock b/examples/bridge/sn/Scarb.lock deleted file mode 100644 index 7108cde3..00000000 --- a/examples/bridge/sn/Scarb.lock +++ /dev/null @@ -1,30 +0,0 @@ -# Code generated by scarb DO NOT EDIT. -version = 1 - -[[package]] -name = "bridge" -version = "0.1.0" -dependencies = [ - "dojo", - "token", -] - -[[package]] -name = "dojo" -version = "0.4.4" -source = "git+https://github.com/dojoengine/dojo?tag=v0.4.4#8afd8c903d71083b8487a5b4a0cfc9360dee0772" -dependencies = [ - "dojo_plugin", -] - -[[package]] -name = "dojo_plugin" -version = "0.3.11" -source = "git+https://github.com/dojoengine/dojo?tag=v0.3.11#1e651b5d4d3b79b14a7d8aa29a92062fcb9e6659" - -[[package]] -name = "token" -version = "0.0.0" -dependencies = [ - "dojo", -] diff --git a/examples/bridge/sn/Scarb.toml b/examples/bridge/sn/Scarb.toml deleted file mode 100644 index 59777f07..00000000 --- a/examples/bridge/sn/Scarb.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "bridge" -version = "0.1.0" - -# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html - -[dependencies] -# not using workspace, otherwise all contracts/models get built & included in manifest -dojo = { git = "https://github.com/dojoengine/dojo", tag = "v0.4.4" } -token = { path = "../../../token" } - -[scripts] -katana_msg = "katana --messaging anvil.messaging.json --dev" -migrate = "sozo build && sozo migrate && ./scripts/initialize.sh local" - -get_balance = "sozo model get ERC20BalanceModel 0x792b78f74ae3631aa8795da847d57d7a45511f7c4711c4e81f2df2dac0fc177 0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973 --world 0x4f5310a18e23b0d3b20e58156d2a9552c16e6995b30d633911ee85ba5aeeeda --rpc-url http://localhost:5050" -withdraw = "sozo execute -c 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266,0x3635c9adc5dea00000,0 0x2ff2f9994ba7e039f50190cb3b3dc538d9abf7201acbe5a6a7aff686dd40d89 initiate_withdrawal" - -[tool.dojo.env] -# Katana -account_address = "0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973" -private_key = "0x1800000000300000180000000000030000000000003006001800006600" -rpc_url = "http://localhost:5050" - -[tool.dojo.world] -name = "Dojo Bridge" -description = "Dojo Bridge" - -[[target.dojo]] -build-external-contracts = [ - "token::components::security::initializable::initializable_model", - "token::components::token::erc20::erc20_metadata::erc_20_metadata_model", - "token::components::token::erc20::erc20_balance::erc_20_balance_model", - "token::components::token::erc20::erc20_allowance::erc_20_allowance_model", - "token::components::token::erc20::erc20_mintable::erc_20_mintable_model", - "token::components::token::erc20::erc20_burnable::erc_20_burnable_model", - "token::components::token::erc20::erc20_bridgeable::erc_20_bridgeable_model", -] - - diff --git a/examples/bridge/sn/accounts/starkli_katana.json b/examples/bridge/sn/accounts/starkli_katana.json deleted file mode 100644 index ab25a943..00000000 --- a/examples/bridge/sn/accounts/starkli_katana.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": 1, - "variant": { - "type": "open_zeppelin", - "version": 1, - "public_key": "0x2b191c2f3ecf685a91af7cf72a43e7b90e2e41220175de5c4f7498981b10053" - }, - "deployment": { - "status": "deployed", - "class_hash": "0x04d07e40e93398ed3c76981e72dd1fd22557a78ce36c0515f679e27f0bb5bc5f", - "address": "0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973" - } -} diff --git a/examples/bridge/sn/anvil.messaging.json b/examples/bridge/sn/anvil.messaging.json deleted file mode 100644 index cd6154d3..00000000 --- a/examples/bridge/sn/anvil.messaging.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "chain": "ethereum", - "rpc_url": "http://127.0.0.1:8545", - "contract_address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", - "sender_address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "private_key": "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - "interval": 2, - "from_block": 0 -} - diff --git a/examples/bridge/sn/scripts/fund.sh b/examples/bridge/sn/scripts/fund.sh deleted file mode 100755 index f37c3c5f..00000000 --- a/examples/bridge/sn/scripts/fund.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -euo pipefail -pushd $(dirname "$0")/.. - -sleep 1 - -export ADDR_TO_FUND=$1 -export RPC_URL="http://localhost:5050" -export FEE_TOKEN_ADDRESS="0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" - -starkli invoke --rpc $RPC_URL --account ./accounts/starkli_katana.json \ ---private-key 0x1800000000300000180000000000030000000000003006001800006600 \ -$FEE_TOKEN_ADDRESS transfer $ADDR_TO_FUND 1000000000000000000 0 diff --git a/examples/bridge/sn/scripts/initialize.sh b/examples/bridge/sn/scripts/initialize.sh deleted file mode 100755 index 9d1fb0c2..00000000 --- a/examples/bridge/sn/scripts/initialize.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash -set -euo pipefail -pushd $(dirname "$0")/.. - -sleep 1 - -# export TX_SLEEP=200 # goerli ... -export TX_SLEEP=1 -export WORLD_ADDRESS=$(cat ./target/dev/manifest.json | jq -r '.world.address') - -export DOJO_TOKEN_ADDRESS=$(cat ./target/dev/manifest.json | jq -r '.contracts[] | select(.name == "dojo_bridge::dojo_token::dojo_token" ).address') -export DOJO_BRIDGE_ADDRESS=$(cat ./target/dev/manifest.json | jq -r '.contracts[] | select(.name == "dojo_bridge::dojo_bridge::dojo_bridge" ).address') - -export CAIRO_DOJO_TOKEN_NAME=$(starkli to-cairo-string $DOJO_TOKEN_NAME) -export CAIRO_DOJO_TOKEN_SYMBOL=$(starkli to-cairo-string $DOJO_TOKEN_SYMBOL) - -echo "---------------------------------------------------------------------------" -echo rpc : $RPC_URL -echo world : $WORLD_ADDRESS -echo "---------------------------------------------------------------------------" -echo token : $DOJO_TOKEN_ADDRESS -echo bridge: $DOJO_BRIDGE_ADDRESS -echo "---------------------------------------------------------------------------" -echo L1_BRIDGE_ADDRESS : $L1_BRIDGE_ADDRESS -echo DOJO_TOKEN_NAME : $DOJO_TOKEN_NAME $CAIRO_DOJO_TOKEN_NAME -echo DOJO_TOKEN_SYMBOL : $DOJO_TOKEN_SYMBOL $CAIRO_DOJO_TOKEN_SYMBOL -echo "---------------------------------------------------------------------------" -echo ACCOUNT_ADDRESS : $ACCOUNT_ADDRESS -echo SOZO_PARAMS : $SOZO_PARAMS -echo "---------------------------------------------------------------------------" - - -sleep 5 - -# enable system -> component authorizations -DOJO_TOKEN_COMPONENTS=( "ERC20MetadataModel" "ERC20BalanceModel" "ERC20AllowanceModel" "ERC20BridgeableModel" ) -DOJO_BRIDGE_COMPONENTS=("DojoBridgeModel") - - -for component in ${DOJO_TOKEN_COMPONENTS[@]}; do - sozo auth writer $component $DOJO_TOKEN_ADDRESS --world $WORLD_ADDRESS $SOZO_PARAMS - sleep $TX_SLEEP -done - -for component in ${DOJO_BRIDGE_COMPONENTS[@]}; do - sozo auth writer $component $DOJO_BRIDGE_ADDRESS --world $WORLD_ADDRESS $SOZO_PARAMS - sleep $TX_SLEEP -done - -printf "Default authorizations have been successfully set.\n" -sleep 2 -echo "Initialization..." - - -# dojo_token -# fn initializer(ref self: ContractState, name: felt252, symbol: felt252, l2_bridge_address: ContractAddress) -echo "Initialize token" -sozo execute $DOJO_TOKEN_ADDRESS initializer -c $CAIRO_DOJO_TOKEN_NAME,$CAIRO_DOJO_TOKEN_SYMBOL,$DOJO_BRIDGE_ADDRESS $SOZO_PARAMS -sleep $TX_SLEEP - -# dojo_bridge -# fn initializer(ref self: ContractState, l1_bridge: felt252, l2_token: ContractAddress) -echo "Initialize bridge" -sozo execute $DOJO_BRIDGE_ADDRESS initializer -c $L1_BRIDGE_ADDRESS,$DOJO_TOKEN_ADDRESS $SOZO_PARAMS -sleep $TX_SLEEP - - diff --git a/examples/bridge/sn/src/dojo_bridge.cairo b/examples/bridge/sn/src/dojo_bridge.cairo deleted file mode 100644 index 67933bcb..00000000 --- a/examples/bridge/sn/src/dojo_bridge.cairo +++ /dev/null @@ -1,190 +0,0 @@ -use starknet::{ContractAddress, ClassHash}; -use dojo::world::IWorldDispatcher; - -#[starknet::interface] -trait IDojoBridge { - // IWorldProvider - fn world(self: @TState, ) -> IWorldDispatcher; - - // IUpgradeable - fn upgrade(ref self: TState, new_class_hash: ClassHash); - - // WITHOUT INTERFACE !!! - fn initializer(ref self: TState, l1_bridge: felt252, l2_token: ContractAddress); - fn initiate_withdrawal(ref self: TState, l1_recipient: felt252, amount: u256); - fn get_l1_bridge(self: @TState, ) -> felt252; - fn get_token(self: @TState, ) -> ContractAddress; - fn dojo_resource(self: @TState, ) -> felt252; -} - -/// -/// Model -/// - -#[derive(Model, Copy, Drop, Serde)] -struct DojoBridgeModel { - #[key] - bridge: ContractAddress, - // address L1 bridge contract address, the L1 counterpart to this contract - l1_bridge: felt252, - // Dojo ERC20 token on Starknet - l2_token: ContractAddress -} - - -#[dojo::contract] -mod dojo_bridge { - use super::DojoBridgeModel; - use starknet::ContractAddress; - use starknet::{get_contract_address, get_caller_address}; - - use token::components::token::erc20::erc20_bridgeable::{ - IERC20Bridgeable, IERC20BridgeableDispatcher, IERC20BridgeableDispatcherTrait - }; - - use token::components::security::initializable::initializable_component; - - component!(path: initializable_component, storage: initializable, event: InitializableEvent); - - #[storage] - struct Storage { - #[substorage(v0)] - initializable: initializable_component::Storage, - } - - #[event] - #[derive(Copy, Drop, starknet::Event)] - enum Event { - InitializableEvent: initializable_component::Event, - DepositHandled: DepositHandled, - WithdrawalInitiated: WithdrawalInitiated, - } - - #[derive(Copy, Drop, starknet::Event)] - struct DepositHandled { - recipient: ContractAddress, - amount: u256 - } - - #[derive(Copy, Drop, starknet::Event)] - struct WithdrawalInitiated { - #[key] - sender: ContractAddress, - recipient: felt252, - amount: u256 - } - - mod Errors { - const CALLER_IS_NOT_OWNER: felt252 = 'Bridge: caller is not owner'; - const INVALID_L1_ORIGIN: felt252 = 'Bridge: invalid L1 origin'; - - const L1_ADDRESS_CANNOT_BE_ZERO: felt252 = 'Bridge: L1 address cannot be 0'; - const L1_ADDRESS_OUT_OF_BOUNDS: felt252 = 'Bridge: L1 addr out of bounds'; - const INVALID_RECIPIENT: felt252 = 'Bridge: invalid recipient'; - } - - - // operation ID sent in the message payload to L1 - const PROCESS_WITHDRAWAL: felt252 = 1; - - // Ethereum addresses are bound to 2**160 - const ETH_ADDRESS_BOUND: u256 = 0x10000000000000000000000000000000000000000_u256; - - impl InitializableImpl = initializable_component::InitializableImpl; - impl InitializableInternalImpl = initializable_component::InternalImpl; - - // - // Initializer - // - - #[external(v0)] - #[generate_trait] - impl ERC20InitializerImpl of ERC20InitializerTrait { - fn initializer(ref self: ContractState, l1_bridge: felt252, l2_token: ContractAddress) { - assert( - self.world().is_owner(get_caller_address(), get_contract_address().into()), - Errors::CALLER_IS_NOT_OWNER - ); - - // one time bridge initialization - set!( - self.world(), DojoBridgeModel { bridge: get_contract_address(), l1_bridge, l2_token } - ); - - // reverts if already initialized - self.initializable.initialize(); - } - } - - // - // L1 Handler - // - - #[l1_handler] - fn handle_deposit( - ref self: ContractState, from_address: felt252, recipient: ContractAddress, amount: u256 - ) { - let data = self.get_data(); - assert(from_address == data.l1_bridge, Errors::INVALID_L1_ORIGIN); - - // mint token - let token_dispatcher = IERC20BridgeableDispatcher { contract_address: data.l2_token }; - token_dispatcher.mint(recipient, amount); - - let event = DepositHandled { recipient, amount }; - - self.emit(event.clone()); - emit!(self.world(), (Event::DepositHandled(event))); - } - - // - // Impls - // - - #[external(v0)] - #[generate_trait] - impl DojoBridgeImpl of DojoBridgeTrait { - fn initiate_withdrawal(ref self: ContractState, l1_recipient: felt252, amount: u256) { - let data = self.get_data(); - let caller = get_caller_address(); - - assert(l1_recipient.is_non_zero(), Errors::L1_ADDRESS_CANNOT_BE_ZERO); - assert(l1_recipient.into() < ETH_ADDRESS_BOUND, Errors::L1_ADDRESS_OUT_OF_BOUNDS); - assert(l1_recipient != data.l1_bridge, Errors::INVALID_RECIPIENT); - - // burn token - let token_dispatcher = IERC20BridgeableDispatcher { contract_address: data.l2_token }; - token_dispatcher.burn(caller, amount); - - let message: Array = array![ - PROCESS_WITHDRAWAL, l1_recipient, amount.low.into(), amount.high.into() - ]; - - // send msg to L1 - starknet::syscalls::send_message_to_l1_syscall(data.l1_bridge, message.span()); - - let event = WithdrawalInitiated { sender: caller, recipient: l1_recipient, amount }; - - self.emit(event.clone()); - emit!(self.world(), (Event::WithdrawalInitiated(event))); - } - - fn get_l1_bridge(self: @ContractState) -> felt252 { - self.get_data().l1_bridge - } - - fn get_token(self: @ContractState) -> ContractAddress { - self.get_data().l2_token - } - } - - - #[generate_trait] - impl InternalImpl of InternalTrait { - fn get_data(self: @ContractState) -> DojoBridgeModel { - get!(self.world(), get_contract_address(), (DojoBridgeModel)) - } - - } -} - diff --git a/examples/bridge/sn/src/dojo_token.cairo b/examples/bridge/sn/src/dojo_token.cairo deleted file mode 100644 index 71ef647f..00000000 --- a/examples/bridge/sn/src/dojo_token.cairo +++ /dev/null @@ -1,207 +0,0 @@ -use starknet::{ContractAddress, ClassHash}; -use dojo::world::IWorldDispatcher; - -#[starknet::interface] -trait IDojoToken { - // IWorldProvider - fn world(self: @TState,) -> IWorldDispatcher; - - // IUpgradeable - fn upgrade(ref self: TState, new_class_hash: ClassHash); - - // IERC20MetadataTotalSupply - fn total_supply(self: @TState,) -> u256; - - // IERC20MetadataTotalSupplyCamel - fn totalSupply(self: @TState,) -> u256; - - // IERC20Balance - fn balance_of(self: @TState, account: ContractAddress) -> u256; - fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool; - fn transfer_from( - ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256 - ) -> bool; - - // IERC20BalanceCamel - fn balanceOf(self: @TState, account: ContractAddress) -> u256; - fn transferFrom( - ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256 - ) -> bool; - - // IERC20Allowance - fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256; - fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool; - - // IERC20Metadata - fn decimals(self: @TState,) -> u8; - fn name(self: @TState,) -> felt252; - fn symbol(self: @TState,) -> felt252; - - // IERC20SafeAllowance - fn decrease_allowance( - ref self: TState, spender: ContractAddress, subtracted_value: u256 - ) -> bool; - fn increase_allowance(ref self: TState, spender: ContractAddress, added_value: u256) -> bool; - - // IERC20SafeAllowanceCamel - fn decreaseAllowance(ref self: TState, spender: ContractAddress, subtractedValue: u256) -> bool; - fn increaseAllowance(ref self: TState, spender: ContractAddress, addedValue: u256) -> bool; - - // IERC20Bridgeable - fn burn(ref self: TState, account: ContractAddress, amount: u256); - fn l2_bridge_address(self: @TState,) -> ContractAddress; - fn mint(ref self: TState, recipient: ContractAddress, amount: u256); - - // WITHOUT INTERFACE !!! - fn initializer( - ref self: TState, name: felt252, symbol: felt252, l2_bridge_address: ContractAddress - ); - fn dojo_resource(self: @TState,) -> felt252; -} - - -#[dojo::contract] -mod dojo_token { - use token::erc20::interface; - use starknet::ContractAddress; - use starknet::{get_caller_address, get_contract_address}; - - use token::components::security::initializable::initializable_component; - - use token::components::token::erc20::erc20_metadata::erc20_metadata_component; - use token::components::token::erc20::erc20_balance::erc20_balance_component; - use token::components::token::erc20::erc20_allowance::erc20_allowance_component; - use token::components::token::erc20::erc20_mintable::erc20_mintable_component; - use token::components::token::erc20::erc20_burnable::erc20_burnable_component; - use token::components::token::erc20::erc20_bridgeable::erc20_bridgeable_component; - - component!(path: initializable_component, storage: initializable, event: InitializableEvent); - - component!(path: erc20_metadata_component, storage: erc20_metadata, event: ERC20MetadataEvent); - component!(path: erc20_balance_component, storage: erc20_balance, event: ERC20BalanceEvent); - component!( - path: erc20_allowance_component, storage: erc20_allowance, event: ERC20AllowanceEvent - ); - component!(path: erc20_mintable_component, storage: erc20_mintable, event: ERC20MintableEvent); - component!(path: erc20_burnable_component, storage: erc20_burnable, event: ERC20BurnableEvent); - component!( - path: erc20_bridgeable_component, storage: erc20_bridgeable, event: ERC20BridgeableEvent - ); - - #[storage] - struct Storage { - #[substorage(v0)] - initializable: initializable_component::Storage, - #[substorage(v0)] - erc20_metadata: erc20_metadata_component::Storage, - #[substorage(v0)] - erc20_balance: erc20_balance_component::Storage, - #[substorage(v0)] - erc20_allowance: erc20_allowance_component::Storage, - #[substorage(v0)] - erc20_mintable: erc20_mintable_component::Storage, - #[substorage(v0)] - erc20_burnable: erc20_burnable_component::Storage, - #[substorage(v0)] - erc20_bridgeable: erc20_bridgeable_component::Storage, - } - - #[event] - #[derive(Copy, Drop, starknet::Event)] - enum Event { - #[flat] - InitializableEvent: initializable_component::Event, - #[flat] - ERC20MetadataEvent: erc20_metadata_component::Event, - #[flat] - ERC20BalanceEvent: erc20_balance_component::Event, - #[flat] - ERC20AllowanceEvent: erc20_allowance_component::Event, - #[flat] - ERC20MintableEvent: erc20_mintable_component::Event, - #[flat] - ERC20BurnableEvent: erc20_burnable_component::Event, - #[flat] - ERC20BridgeableEvent: erc20_bridgeable_component::Event, - } - - mod Errors { - const CALLER_IS_NOT_OWNER: felt252 = 'ERC20: caller is not owner'; - } - - - impl InitializableImpl = initializable_component::InitializableImpl; - - #[abi(embed_v0)] - impl ERC20MetadataTotalSupplyImpl = - erc20_metadata_component::ERC20MetadataTotalSupplyImpl; - - #[abi(embed_v0)] - impl ERC20MetadataTotalSupplyCamelImpl = - erc20_metadata_component::ERC20MetadataTotalSupplyCamelImpl; - - #[abi(embed_v0)] - impl ERC20BalanceImpl = - erc20_balance_component::ERC20BalanceImpl; - - #[abi(embed_v0)] - impl ERC20BalanceCamelImpl = - erc20_balance_component::ERC20BalanceCamelImpl; - - #[abi(embed_v0)] - impl ERC20AllowanceImpl = - erc20_allowance_component::ERC20AllowanceImpl; - - #[abi(embed_v0)] - impl ERC20MetadataImpl = - erc20_metadata_component::ERC20MetadataImpl; - - #[abi(embed_v0)] - impl ERC20SafeAllowanceImpl = - erc20_allowance_component::ERC20SafeAllowanceImpl; - - #[abi(embed_v0)] - impl ERC20SafeAllowanceCamelImpl = - erc20_allowance_component::ERC20SafeAllowanceCamelImpl; - - #[abi(embed_v0)] - impl ERC20BridgeableImpl = - erc20_bridgeable_component::ERC20BridgeableImpl; - - // - // Internal Impls - // - - impl InitializableInternalImpl = initializable_component::InternalImpl; - impl ERC20MetadataInternalImpl = erc20_metadata_component::InternalImpl; - impl ERC20BalanceInternalImpl = erc20_balance_component::InternalImpl; - impl ERC20AllowanceInternalImpl = erc20_allowance_component::InternalImpl; - impl ERC20MintableInternalImpl = erc20_mintable_component::InternalImpl; - impl ERC20BurnableInternalImpl = erc20_burnable_component::InternalImpl; - impl ERC20BridgeableInternalImpl = erc20_bridgeable_component::InternalImpl; - - // - // Initializer - // - - #[external(v0)] - #[generate_trait] - impl ERC20InitializerImpl of ERC20InitializerTrait { - fn initializer( - ref self: ContractState, - name: felt252, - symbol: felt252, - l2_bridge_address: ContractAddress, - ) { - assert( - self.world().is_owner(get_caller_address(), get_contract_address().into()), - Errors::CALLER_IS_NOT_OWNER - ); - - self.erc20_metadata.initialize(name, symbol, 18); - self.erc20_bridgeable.initialize(l2_bridge_address); - - self.initializable.initialize(); - } - } -} diff --git a/examples/bridge/sn/src/lib.cairo b/examples/bridge/sn/src/lib.cairo deleted file mode 100644 index 2c3244b5..00000000 --- a/examples/bridge/sn/src/lib.cairo +++ /dev/null @@ -1,9 +0,0 @@ -mod dojo_token; -mod dojo_bridge; - -#[cfg(test)] -mod tests { - mod tests; -} - - diff --git a/examples/bridge/sn/src/tests/tests.cairo b/examples/bridge/sn/src/tests/tests.cairo deleted file mode 100644 index 803ffb55..00000000 --- a/examples/bridge/sn/src/tests/tests.cairo +++ /dev/null @@ -1,132 +0,0 @@ -use core::array::SpanTrait; -use starknet::ContractAddress; -use starknet::testing; -use zeroable::Zeroable; - -use integer::BoundedInt; -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; -use dojo::test_utils::spawn_test_world; -use token::tests::constants::{ - ZERO, OWNER, SPENDER, RECIPIENT, BRIDGE, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE -}; - -use token::tests::utils; - -use token::components::token::erc20::erc20_metadata::{erc_20_metadata_model, ERC20MetadataModel,}; -use token::components::token::erc20::erc20_metadata::erc20_metadata_component::{ - ERC20MetadataImpl, ERC20MetadataTotalSupplyImpl, InternalImpl as ERC20MetadataInternalImpl -}; - -use token::components::token::erc20::erc20_balance::{erc_20_balance_model, ERC20BalanceModel,}; -use token::components::token::erc20::erc20_balance::erc20_balance_component::{ - Transfer, ERC20BalanceImpl, InternalImpl as ERC20BalanceInternalImpl -}; - -use token::components::token::erc20::erc20_allowance::{ - erc_20_allowance_model, ERC20AllowanceModel, -}; -use token::components::token::erc20::erc20_allowance::erc20_allowance_component::{ - Approval, ERC20AllowanceImpl, InternalImpl as ERC20AllownceInternalImpl, ERC20SafeAllowanceImpl, - ERC20SafeAllowanceCamelImpl -}; - -use token::components::token::erc20::erc20_bridgeable::{ - erc_20_bridgeable_model, ERC20BridgeableModel -}; -use token::components::token::erc20::erc20_bridgeable::erc20_bridgeable_component::{ - ERC20BridgeableImpl -}; - -use token::components::token::erc20::erc20_mintable::erc20_mintable_component::InternalImpl as ERC20MintableInternalImpl; -use token::components::token::erc20::erc20_burnable::erc20_burnable_component::InternalImpl as ERC20BurnableInternalImpl; - -use bridge::dojo_token::{ - dojo_token, IDojoToken, IDojoTokenDispatcher, IDojoTokenDispatcherTrait -}; -use bridge::dojo_bridge::{ - dojo_bridge_model, dojo_bridge, IDojoBridge, IDojoBridgeDispatcher, IDojoBridgeDispatcherTrait -}; - -use token::components::tests::token::erc20::test_erc20_allowance::{ - assert_event_approval, assert_only_event_approval -}; -use token::components::tests::token::erc20::test_erc20_balance::{ - assert_event_transfer, assert_only_event_transfer -}; - - -const L1BRIDGE: felt252 = 'L1BRIDGE'; - -// -// Setup -// - -fn setup() -> (IWorldDispatcher, IDojoTokenDispatcher, IDojoBridgeDispatcher) { - let world = spawn_test_world( - array![ - erc_20_allowance_model::TEST_CLASS_HASH, - erc_20_balance_model::TEST_CLASS_HASH, - erc_20_metadata_model::TEST_CLASS_HASH, - erc_20_bridgeable_model::TEST_CLASS_HASH, - dojo_bridge_model::TEST_CLASS_HASH, - ] - ); - - // deploy token - let mut dojo_token_dispatcher = IDojoTokenDispatcher { - contract_address: world - .deploy_contract('salt', dojo_token::TEST_CLASS_HASH.try_into().unwrap(), array![].span()) - }; - - // deploy bridge - let mut dojo_bridge_dispatcher = IDojoBridgeDispatcher { - contract_address: world - .deploy_contract('salt', dojo_bridge::TEST_CLASS_HASH.try_into().unwrap(),array![].span()) - }; - - // setup auth for dojo_token - world.grant_writer(selector!("ERC20AllowanceModel"), dojo_token_dispatcher.contract_address); - world.grant_writer(selector!("ERC20BalanceModel"), dojo_token_dispatcher.contract_address); - world.grant_writer(selector!("ERC20MetadataModel"), dojo_token_dispatcher.contract_address); - world.grant_writer(selector!("ERC20BridgeableModel"), dojo_token_dispatcher.contract_address); - - // setup auth for dojo_bridge - world.grant_writer(selector!("DojoBridgeModel"), dojo_bridge_dispatcher.contract_address); - - - // initialize dojo_token - dojo_token_dispatcher.initializer(NAME, SYMBOL, dojo_bridge_dispatcher.contract_address); - - // initialize dojo_bridge - dojo_bridge_dispatcher.initializer( L1BRIDGE, dojo_token_dispatcher.contract_address); - dojo_bridge_dispatcher.initializer( L1BRIDGE, dojo_token_dispatcher.contract_address); - - // drop all events - utils::drop_all_events(dojo_token_dispatcher.contract_address); - utils::drop_all_events(dojo_bridge_dispatcher.contract_address); - utils::drop_all_events(world.contract_address); - - (world, dojo_token_dispatcher, dojo_bridge_dispatcher) -} - - -// -// initializer -// - -#[test] -#[available_gas(30000000)] -fn test_initializers() { - let (world, mut dojo_token, mut dojo_bridge) = setup(); - - assert(dojo_token.total_supply() == 0, 'Should eq 0'); - assert(dojo_token.name() == NAME, 'Name should be NAME'); - assert(dojo_token.symbol() == SYMBOL, 'Symbol should be SYMBOL'); - assert(dojo_token.decimals() == DECIMALS, 'Decimals should be 18'); - - assert(dojo_token.l2_bridge_address() == dojo_bridge.contract_address, 'invalid l2_bridge_address'); - - assert(dojo_bridge.get_l1_bridge() == L1BRIDGE, 'Should be L1BRIDGE'); - assert(dojo_bridge.get_token() == dojo_token.contract_address, 'Invalid get_token'); - -} diff --git a/examples/chess/.gitignore b/examples/chess/.gitignore deleted file mode 100644 index 1de56593..00000000 --- a/examples/chess/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target \ No newline at end of file diff --git a/examples/chess/Scarb.lock b/examples/chess/Scarb.lock deleted file mode 100644 index 42e0d6ee..00000000 --- a/examples/chess/Scarb.lock +++ /dev/null @@ -1,22 +0,0 @@ -# Code generated by scarb DO NOT EDIT. -version = 1 - -[[package]] -name = "chess" -version = "0.4.0" -dependencies = [ - "dojo", -] - -[[package]] -name = "dojo" -version = "0.4.1" -source = "git+https://github.com/dojoengine/dojo#570f2d0c74073366084c337398b212aa648bade6" -dependencies = [ - "dojo_plugin", -] - -[[package]] -name = "dojo_plugin" -version = "0.3.11" -source = "git+https://github.com/dojoengine/dojo?tag=v0.3.11#1e651b5d4d3b79b14a7d8aa29a92062fcb9e6659" diff --git a/examples/chess/Scarb.toml b/examples/chess/Scarb.toml deleted file mode 100644 index f329d892..00000000 --- a/examples/chess/Scarb.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -cairo-version = "2.5.4" -name = "chess" -version = "0.6.0-alpha.6" - -[cairo] -sierra-replace-ids = true - -[dependencies] -dojo.workspace = true - -[[target.dojo]] - -[tool.dojo] -initializer_class_hash = "0xbeef" - -[tool.dojo.env] -rpc_url = "http://localhost:5050/" -# Default account for katana with seed = 0 -account_address = "0x6162896d1d7ab204c7ccac6dd5f8e9e7c25ecd5ae4fcb4ad32e57786bb46e03" -private_key = "0x1800000000300000180000000000030000000000003006001800006600" -world_address = "0x446f1f19ba951b59935df72974f8ba6060e5fbb411ca21d3e3e3812e3eb8df8" diff --git a/examples/chess/src/actions.cairo b/examples/chess/src/actions.cairo deleted file mode 100644 index 47928e1d..00000000 --- a/examples/chess/src/actions.cairo +++ /dev/null @@ -1,164 +0,0 @@ -use starknet::ContractAddress; -use chess::models::piece::Vec2; - -#[dojo::interface] -trait IActions { - fn move( - ref world: IWorldDispatcher, - curr_position: Vec2, - next_position: Vec2, - caller: ContractAddress, - game_id: u32 - ); - fn spawn( - ref world: IWorldDispatcher, white_address: ContractAddress, black_address: ContractAddress - ) -> u32; -} - -#[dojo::contract] -mod actions { - use chess::models::player::{Player, Color, PlayerTrait}; - use chess::models::piece::{Piece, PieceType, PieceTrait}; - use chess::models::game::{Game, GameTurn, GameTurnTrait}; - use super::{ContractAddress, IActions, Vec2}; - - #[abi(embed_v0)] - impl IActionsImpl of IActions { - fn spawn( - ref world: IWorldDispatcher, - white_address: ContractAddress, - black_address: ContractAddress - ) -> u32 { - let game_id = world.uuid(); - - // set Players - set!( - world, - ( - Player { game_id, address: black_address, color: Color::Black }, - Player { game_id, address: white_address, color: Color::White }, - ) - ); - - // set Game and GameTurn - set!( - world, - ( - Game { - game_id, winner: Color::None, white: white_address, black: black_address - }, - GameTurn { game_id, player_color: Color::White }, - ) - ); - - // set Pieces - set!( - world, - (Piece { - game_id, - color: Color::White, - position: Vec2 { x: 0, y: 0 }, - piece_type: PieceType::Rook - }) - ); - set!( - world, - (Piece { - game_id, - color: Color::White, - position: Vec2 { x: 0, y: 1 }, - piece_type: PieceType::Pawn - }) - ); - set!( - world, - (Piece { - game_id, - color: Color::Black, - position: Vec2 { x: 1, y: 6 }, - piece_type: PieceType::Pawn - }) - ); - set!( - world, - (Piece { - game_id, - color: Color::White, - position: Vec2 { x: 1, y: 0 }, - piece_type: PieceType::Knight - }) - ); - set!( - world, - (Piece { - game_id, - color: Color::None, - position: Vec2 { x: 0, y: 2 }, - piece_type: PieceType::None - }) - ); - - set!( - world, - (Piece { - game_id, - color: Color::None, - position: Vec2 { x: 0, y: 3 }, - piece_type: PieceType::None - }) - ); - set!( - world, - (Piece { - game_id, - color: Color::None, - position: Vec2 { x: 1, y: 4 }, - piece_type: PieceType::None - }) - ); - - //the rest of the positions on the board goes here.... - - game_id - } - fn move( - ref world: IWorldDispatcher, - curr_position: Vec2, - next_position: Vec2, - caller: ContractAddress, - game_id: u32 - ) { - let mut current_piece = get!(world, (game_id, curr_position), (Piece)); - // check if next_position is out of board or not - assert!(!PieceTrait::is_out_of_board(next_position), "Should be inside board"); - - // check if this is the right move for this piece type - assert!( - current_piece.is_right_piece_move(next_position), "Illegal move for type of piece" - ); - // Get piece data from to next_position in the board - let mut next_position_piece = get!(world, (game_id, next_position), (Piece)); - - let player = get!(world, (game_id, caller), (Player)); - // check if there is already a piece in next_position - assert!( - next_position_piece.piece_type == PieceType::None - || player.is_not_my_piece(next_position_piece.color), - "Already same color piece exist" - ); - - next_position_piece.piece_type = current_piece.piece_type; - next_position_piece.color = player.color; - // make current_piece piece none - current_piece.piece_type = PieceType::None; - current_piece.color = Color::None; - set!(world, (next_position_piece)); - set!(world, (current_piece)); - - // change turn - let mut game_turn = get!(world, game_id, (GameTurn)); - game_turn.player_color = game_turn.next_turn(); - set!(world, (game_turn)); - } - } -} diff --git a/examples/chess/src/lib.cairo b/examples/chess/src/lib.cairo deleted file mode 100644 index f4d1bd13..00000000 --- a/examples/chess/src/lib.cairo +++ /dev/null @@ -1,4 +0,0 @@ -mod actions; -mod models; -mod tests; - diff --git a/examples/chess/src/models.cairo b/examples/chess/src/models.cairo deleted file mode 100644 index 60825839..00000000 --- a/examples/chess/src/models.cairo +++ /dev/null @@ -1,3 +0,0 @@ -mod game; -mod piece; -mod player; diff --git a/examples/chess/src/models/game.cairo b/examples/chess/src/models/game.cairo deleted file mode 100644 index 0c822a00..00000000 --- a/examples/chess/src/models/game.cairo +++ /dev/null @@ -1,33 +0,0 @@ -use chess::models::player::Color; -use starknet::ContractAddress; - -#[dojo::model] -#[derive(Drop, Serde)] -struct Game { - #[key] - game_id: u32, - winner: Color, - white: ContractAddress, - black: ContractAddress -} - -#[dojo::model] -#[derive(Drop, Serde)] -struct GameTurn { - #[key] - game_id: u32, - player_color: Color -} - -trait GameTurnTrait { - fn next_turn(self: @GameTurn) -> Color; -} -impl GameTurnImpl of GameTurnTrait { - fn next_turn(self: @GameTurn) -> Color { - match self.player_color { - Color::White => Color::Black, - Color::Black => Color::White, - Color::None => panic(array!['Illegal turn']) - } - } -} diff --git a/examples/chess/src/models/piece.cairo b/examples/chess/src/models/piece.cairo deleted file mode 100644 index 29505e7f..00000000 --- a/examples/chess/src/models/piece.cairo +++ /dev/null @@ -1,100 +0,0 @@ -use chess::models::player::Color; -use starknet::ContractAddress; - -#[dojo::model] -#[derive(Drop, Serde)] -struct Piece { - #[key] - game_id: u32, - #[key] - position: Vec2, - color: Color, - piece_type: PieceType, -} - -#[derive(Copy, Drop, Serde, Introspect)] -struct Vec2 { - x: u32, - y: u32 -} - -trait PieceTrait { - fn is_out_of_board(next_position: Vec2) -> bool; - fn is_right_piece_move(self: @Piece, next_position: Vec2) -> bool; -} - -impl PieceImpl of PieceTrait { - fn is_out_of_board(next_position: Vec2) -> bool { - next_position.x > 7 || next_position.y > 7 - } - - fn is_right_piece_move(self: @Piece, next_position: Vec2) -> bool { - let n_x = next_position.x; - let n_y = next_position.y; - assert!( - !(n_x == *self.position.x && n_y == *self.position.y), "Cannot move same position " - ); - match self.piece_type { - PieceType::Pawn => { - match self.color { - Color::White => { - (n_x == *self.position.x && n_y == *self.position.y + 1) - || (n_x == *self.position.x && n_y == *self.position.y + 2) - || (n_x == *self.position.x + 1 && n_y == *self.position.y + 1) - || (n_x == *self.position.x - 1 && n_y == *self.position.y + 1) - }, - Color::Black => { - (n_x == *self.position.x && n_y == *self.position.y - 1) - || (n_x == *self.position.x && n_y == *self.position.y - 2) - || (n_x == *self.position.x + 1 && n_y == *self.position.y - 1) - || (n_x == *self.position.x - 1 && n_y == *self.position.y - 1) - }, - Color::None => panic(array!['Should not move empty piece']), - } - }, - PieceType::Knight => { n_x == *self.position.x + 2 && n_y == *self.position.y + 1 }, - PieceType::Bishop => { - (n_x <= *self.position.x && n_y <= *self.position.y && *self.position.y - - n_y == *self.position.x - - n_x) - || (n_x <= *self.position.x && n_y >= *self.position.y && *self.position.y - - n_y == *self.position.x - - n_x) - || (n_x >= *self.position.x && n_y <= *self.position.y && *self.position.y - - n_y == *self.position.x - - n_x) - || (n_x >= *self.position.x && n_y >= *self.position.y && *self.position.y - - n_y == *self.position.x - - n_x) - }, - PieceType::Rook => { - (n_x == *self.position.x || n_y != *self.position.y) - || (n_x != *self.position.x || n_y == *self.position.y) - }, - PieceType::Queen => { - (n_x == *self.position.x || n_y != *self.position.y) - || (n_x != *self.position.x || n_y == *self.position.y) - || (n_x != *self.position.x || n_y != *self.position.y) - }, - PieceType::King => { - (n_x <= *self.position.x + 1 && n_y <= *self.position.y + 1) - || (n_x <= *self.position.x + 1 && n_y <= *self.position.y - 1) - || (n_x <= *self.position.x - 1 && n_y <= *self.position.y + 1) - || (n_x <= *self.position.x - 1 && n_y <= *self.position.y - 1) - }, - PieceType::None => panic(array!['Should not move empty piece']), - } - } -} - -#[derive(Serde, Drop, Copy, PartialEq, Introspect)] -enum PieceType { - Pawn, - Knight, - Bishop, - Rook, - Queen, - King, - None, -} - diff --git a/examples/chess/src/models/player.cairo b/examples/chess/src/models/player.cairo deleted file mode 100644 index de9e74cd..00000000 --- a/examples/chess/src/models/player.cairo +++ /dev/null @@ -1,28 +0,0 @@ -use starknet::ContractAddress; - -#[derive(Serde, Drop, Copy, PartialEq, Introspect)] -enum Color { - White, - Black, - None, -} - -#[dojo::model] -#[derive(Drop, Serde)] -struct Player { - #[key] - game_id: u32, - #[key] - address: ContractAddress, - color: Color -} - -trait PlayerTrait { - fn is_not_my_piece(self: @Player, piece_color: Color) -> bool; -} - -impl PalyerImpl of PlayerTrait { - fn is_not_my_piece(self: @Player, piece_color: Color) -> bool { - *self.color != piece_color - } -} diff --git a/examples/chess/src/tests.cairo b/examples/chess/src/tests.cairo deleted file mode 100644 index 96373734..00000000 --- a/examples/chess/src/tests.cairo +++ /dev/null @@ -1,2 +0,0 @@ -mod integration; -mod units; diff --git a/examples/chess/src/tests/integration.cairo b/examples/chess/src/tests/integration.cairo deleted file mode 100644 index 2eff3f1e..00000000 --- a/examples/chess/src/tests/integration.cairo +++ /dev/null @@ -1,64 +0,0 @@ -#[cfg(test)] -mod tests { - use chess::models::piece::{Piece, PieceType, Vec2}; - use dojo::world::IWorldDispatcherTrait; - use chess::tests::units::tests::setup_world; - use chess::actions::{IActionsDispatcher, IActionsDispatcherTrait}; - use chess::models::player::{Color}; - - #[test] - fn integration() { - let white = starknet::contract_address_const::<0x01>(); - let black = starknet::contract_address_const::<0x02>(); - - let (world, actions_system) = setup_world(); - - //system calls - let game_id = actions_system.spawn(white, black); - - //White pawn is setup in (0,1) - let wp_curr_pos = Vec2 { x: 0, y: 1 }; - let a2 = get!(world, (game_id, wp_curr_pos), (Piece)); - assert!(a2.piece_type == PieceType::Pawn, "should be Pawn in (0,1) "); - assert!(a2.color == Color::White, "should be white color "); - assert!(a2.piece_type != PieceType::None, "should have piece in (0,1) "); - - //Black pawn is setup in (1,6) - let bp_curr_pos = Vec2 { x: 1, y: 6 }; - let b7 = get!(world, (game_id, bp_curr_pos), (Piece)); - assert!(b7.piece_type == PieceType::Pawn, "should be Pawn in (1,6) "); - assert!(b7.color == Color::Black, "should be black color "); - assert!(b7.piece_type != PieceType::None, "should have piece in (1,6) "); - - //Move White Pawn to (0,3) - let wp_next_pos = Vec2 { x: 0, y: 3 }; - actions_system.move(wp_curr_pos, wp_next_pos, white.into(), game_id); - - //White pawn is now in (0,3) - let wp_curr_pos = wp_next_pos; - let a4 = get!(world, (game_id, wp_curr_pos), (Piece)); - assert!(a4.piece_type == PieceType::Pawn, "should be Pawn in (0,3) "); - assert!(a4.color == Color::White, "should be white color "); - assert!(a4.piece_type != PieceType::None, "should have piece in (0,3) "); - - //Move black Pawn to (1,4) - let bp_next_pos = Vec2 { x: 1, y: 4 }; - actions_system.move(bp_curr_pos, bp_next_pos, black.into(), game_id); - - //Black pawn is now in (1,4) - let bp_curr_pos = bp_next_pos; - let b5 = get!(world, (game_id, bp_curr_pos), (Piece)); - assert!(b5.piece_type == PieceType::Pawn, "should be Pawn in (1,4) "); - assert!(b5.color == Color::Black, "should be black color "); - assert!(b5.piece_type != PieceType::None, "should have piece in (1,4) "); - - // Move White Pawn to (1,4) and capture black pawn - actions_system.move(wp_curr_pos, bp_curr_pos, white.into(), game_id); - - let wp_curr_pos = bp_curr_pos; - let b5 = get!(world, (game_id, wp_curr_pos), (Piece)); - assert!(b5.piece_type == PieceType::Pawn, "should be Pawn in (1,4) "); - assert!(b5.color == Color::White, "should be white color "); - assert!(b5.piece_type != PieceType::None, "should have piece in (1,4) "); - } -} diff --git a/examples/chess/src/tests/units.cairo b/examples/chess/src/tests/units.cairo deleted file mode 100644 index a975b878..00000000 --- a/examples/chess/src/tests/units.cairo +++ /dev/null @@ -1,80 +0,0 @@ -#[cfg(test)] -mod tests { - use starknet::ContractAddress; - use dojo::test_utils::{spawn_test_world, deploy_contract}; - use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - use chess::models::player::{Player, Color, player}; - use chess::models::piece::{Piece, PieceType, Vec2, piece}; - use chess::models::game::{Game, GameTurn, game, game_turn}; - use chess::actions::{actions, IActionsDispatcher, IActionsDispatcherTrait}; - - // helper setup function - fn setup_world() -> (IWorldDispatcher, IActionsDispatcher) { - // models - let mut models = array![ - game::TEST_CLASS_HASH, - player::TEST_CLASS_HASH, - game_turn::TEST_CLASS_HASH, - piece::TEST_CLASS_HASH - ]; - // deploy world with models - let world = spawn_test_world(models); - - // deploy systems contract - let contract_address = world - .deploy_contract('salt', actions::TEST_CLASS_HASH.try_into().unwrap(), array![].span()); - let actions_system = IActionsDispatcher { contract_address }; - - (world, actions_system) - } - #[test] - fn test_spawn() { - let white = starknet::contract_address_const::<0x01>(); - let black = starknet::contract_address_const::<0x02>(); - let (world, actions_system) = setup_world(); - - //system calls - let game_id = actions_system.spawn(white, black); - - //get game - let game = get!(world, game_id, (Game)); - let game_turn = get!(world, game_id, (GameTurn)); - assert!(game_turn.player_color == Color::White, "should be white turn "); - assert!(game.white == white, "white address is incorrect "); - assert!(game.black == black, "black address is incorrect "); - - //get a1 piece - let curr_pos = Vec2 { x: 0, y: 0 }; - let a1 = get!(world, (game_id, curr_pos), (Piece)); - assert!(a1.piece_type == PieceType::Rook, "should be Rook "); - assert!(a1.color == Color::White, "should be white color "); - assert!(a1.piece_type != PieceType::None, "should have piece "); - } - #[test] - fn test_move() { - let white = starknet::contract_address_const::<0x01>(); - let black = starknet::contract_address_const::<0x02>(); - - let (world, actions_system) = setup_world(); - let game_id = actions_system.spawn(white, black); - let curr_pos = Vec2 { x: 0, y: 1 }; - let a2 = get!(world, (game_id, curr_pos), (Piece)); - assert!(a2.piece_type == PieceType::Pawn, "should be Pawn "); - assert!(a2.color == Color::White, "should be white color piece 1 "); - assert!(a2.piece_type != PieceType::None, "should have piece "); - - let next_pos = Vec2 { x: 0, y: 2 }; - let game_turn = get!(world, game_id, (GameTurn)); - assert!(game_turn.player_color == Color::White, "should be white player turn "); - actions_system.move(curr_pos, next_pos, white.into(), game_id); - - let curr_pos = next_pos; - let c3 = get!(world, (game_id, curr_pos), (Piece)); - assert!(c3.piece_type == PieceType::Pawn, "should be Pawn "); - assert!(c3.color == Color::White, "should be white color piece 2 "); - assert!(c3.piece_type != PieceType::None, "should have piece "); - - let game_turn = get!(world, game_id, (GameTurn)); - assert!(game_turn.player_color == Color::Black, "should be black player turn "); - } -} diff --git a/examples/hex_map/Scarb.toml b/examples/hex_map/Scarb.toml deleted file mode 100644 index 1e6bd713..00000000 --- a/examples/hex_map/Scarb.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "hex_map" -version = "0.0.0" -description = "Example Hex Map with noise" -homepage = "https://github.com/dojoengine/origami/tree/examples/hex_map" - -[dependencies] -cubit.workspace = true -dojo.workspace = true -origami.workspace = true diff --git a/examples/hex_map/readme.md b/examples/hex_map/readme.md deleted file mode 100644 index 4c9cd554..00000000 --- a/examples/hex_map/readme.md +++ /dev/null @@ -1,5 +0,0 @@ -## Hex map with noise - -This example uses the hex grid origami component along with cubits simplex noise. - -You can replicate the noise in a client to mirror the onchain noise with the offchain noise to provide users with a rich map to explore. diff --git a/examples/hex_map/src/actions.cairo b/examples/hex_map/src/actions.cairo deleted file mode 100644 index de9dbe69..00000000 --- a/examples/hex_map/src/actions.cairo +++ /dev/null @@ -1,230 +0,0 @@ -// internal imports -use core::Into; -use origami::map::hex::{types::Direction}; -use hex_map::models::Position; - -// define the interface -#[dojo::interface] -trait IActions { - fn spawn(ref world: IWorldDispatcher); - fn move(ref world: IWorldDispatcher, direction: Direction); -} - -#[dojo::interface] -trait IActionsComputed { - fn next_position( - world: @IWorldDispatcher, position: Position, direction: Direction - ) -> Position; -} - -// dojo decorator -#[dojo::contract] -mod actions { - use starknet::{ContractAddress, get_caller_address}; - use origami::map::hex::{hex::{IHexTile}, types::{Direction, DirectionIntoFelt252}}; - - use hex_map::models::{Position, Vec2}; - use hex_map::noise::{ITile}; - - use super::{IActions, IActionsComputed}; - - // declaring custom event struct - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - Moved: Moved, - } - - // declaring custom event struct - #[derive(Drop, starknet::Event)] - struct Moved { - player: ContractAddress, - direction: Direction - } - - #[abi(embed_v0)] - impl ActionsComputedImpl of IActionsComputed { - #[computed(Position)] - fn next_position(position: Position, direction: Direction) -> Position { - let mut new_position = position; - - // convert to Hex - let hex_tile = IHexTile::new(position.vec.x, position.vec.y); - - // get next next tile - let next_hex = hex_tile.neighbor(direction); - - // check movable - ITile::check_moveable(next_hex); - - // convert back to Position - new_position.vec = Vec2 { x: next_hex.col, y: next_hex.row }; - - new_position - } - } - - #[abi(embed_v0)] - impl ActionsImpl of IActions { - // ContractState is defined by system decorator expansion - fn spawn(ref world: IWorldDispatcher) { - set!(world, (Position { player: get_caller_address(), vec: Vec2 { x: 10, y: 10 } })); - } - // Moves player in the provided direction. - fn move(ref world: IWorldDispatcher, direction: Direction) { - // Get the address of the current caller, possibly the player's address. - let player = get_caller_address(); - - // Retrieve the player's current position and moves data from the world. - let mut position = get!(world, player, (Position)); - - // // Calculate the player's next position based on the provided direction. - let next = self.next_position(position, direction); - - // Update the world state with the new moves data and position. - set!(world, (next)); - - // Emit an event to the world to notify about the player's move. - emit!(world, (Event::Moved(Moved { player, direction }))); - } - } -} -#[cfg(test)] -mod tests { - use debug::PrintTrait; - use starknet::class_hash::Felt252TryIntoClassHash; - - // import world dispatcher - use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - - // import test utils - use dojo::test_utils::{spawn_test_world, deploy_contract}; - - // import models - use hex_map::models::{position}; - use hex_map::models::{Position, Direction, Vec2}; - - // import actions - use super::{actions, IActionsDispatcher, IActionsDispatcherTrait}; - - fn setup_world() -> (IWorldDispatcher, IActionsDispatcher) { - // models - let mut models = array![position::TEST_CLASS_HASH]; - - // deploy world with models - let world: IWorldDispatcher = spawn_test_world(models); - - // deploy systems contract - let contract_address = world - .deploy_contract('salt', actions::TEST_CLASS_HASH.try_into().unwrap(), array![].span()); - let actions_system = IActionsDispatcher { contract_address }; - - (world, actions_system) - } - - #[test] - fn test_east() { - // caller - let caller = starknet::contract_address_const::<0x0>(); - - let (world, actions_system) = setup_world(); - - // call spawn() - actions_system.spawn(); - - // call move with direction right - actions_system.move(Direction::East(())); - - // get new_position - let new_position = get!(world, caller, Position); - - // check new position x - assert(new_position.vec.x == 11, 'position x is wrong'); - - // check new position y - assert(new_position.vec.y == 10, 'position y is wrong'); - } - - - #[test] - #[should_panic(expected: ('Cannot walk on water', 'ENTRYPOINT_FAILED'))] - fn test_south_east() { - let (_world, actions_system) = setup_world(); - - // call spawn() - actions_system.spawn(); - - // call move with direction right - actions_system.move(Direction::SouthEast(())); - } - - #[test] - fn test_south() { - // caller - let caller = starknet::contract_address_const::<0x0>(); - - let (world, actions_system) = setup_world(); - - // call spawn() - actions_system.spawn(); - - // call move with direction right - actions_system.move(Direction::SouthWest(())); - - // get new_position - let new_position = get!(world, caller, Position); - - // check new position x - assert(new_position.vec.x == 10, 'position x is wrong'); - - // check new position y - assert(new_position.vec.y == 11, 'position y is wrong'); - } - #[test] - #[should_panic(expected: ('Cannot walk on water', 'ENTRYPOINT_FAILED'))] - fn test_north() { - let (_world, actions_system) = setup_world(); - - // call spawn() - actions_system.spawn(); - - // call move with direction right - actions_system.move(Direction::West(())); - } - - #[test] - fn test_north_west() { - // caller - let caller = starknet::contract_address_const::<0x0>(); - - let (world, actions_system) = setup_world(); - - // call spawn() - actions_system.spawn(); - - // call move with direction right - actions_system.move(Direction::NorthWest(())); - - // get new_position - let new_position = get!(world, caller, Position); - - // check new position x - assert(new_position.vec.x == 10, 'position x is wrong'); - - // check new position y - assert(new_position.vec.y == 9, 'position y is wrong'); - } - - #[test] - #[should_panic(expected: ('Cannot walk on water', 'ENTRYPOINT_FAILED'))] - fn test_north_east() { - let (_world, actions_system) = setup_world(); - - // call spawn() - actions_system.spawn(); - - // call move with direction right - actions_system.move(Direction::NorthEast(())); - } -} - diff --git a/examples/hex_map/src/lib.cairo b/examples/hex_map/src/lib.cairo deleted file mode 100644 index d25852da..00000000 --- a/examples/hex_map/src/lib.cairo +++ /dev/null @@ -1,3 +0,0 @@ -mod models; -mod actions; -mod noise; diff --git a/examples/hex_map/src/models.cairo b/examples/hex_map/src/models.cairo deleted file mode 100644 index 60216950..00000000 --- a/examples/hex_map/src/models.cairo +++ /dev/null @@ -1,51 +0,0 @@ -use starknet::ContractAddress; -use origami::map::hex::{types::{Direction}}; - -#[derive(Copy, Drop, Serde, Introspect)] -struct Vec2 { - x: u32, - y: u32 -} - -#[dojo::model] -#[derive(Copy, Drop, Serde)] -struct Position { - #[key] - player: ContractAddress, - vec: Vec2, -} - -trait Vec2Trait { - fn is_zero(self: Vec2) -> bool; - fn is_equal(self: Vec2, b: Vec2) -> bool; -} - -impl Vec2Impl of Vec2Trait { - fn is_zero(self: Vec2) -> bool { - if self.x - self.y == 0 { - return true; - } - false - } - - fn is_equal(self: Vec2, b: Vec2) -> bool { - self.x == b.x && self.y == b.y - } -} -// #[cfg(test)] -// mod tests { -// use super::{Position, Vec2, Vec2Trait}; - -// #[test] -// fn test_vec_is_zero() { -// assert(Vec2Trait::is_zero(Vec2 { x: 0, y: 0 }), 'not zero'); -// } - -// #[test] -// fn test_vec_is_equal() { -// let position = Vec2 { x: 420, y: 0 }; -// assert(position.is_equal(Vec2 { x: 420, y: 0 }), 'not equal'); -// } -// } - - diff --git a/examples/hex_map/src/noise.cairo b/examples/hex_map/src/noise.cairo deleted file mode 100644 index c3b2dc58..00000000 --- a/examples/hex_map/src/noise.cairo +++ /dev/null @@ -1,83 +0,0 @@ -// -// -// Unique buisness logic of your world. It imports both the hex from origami and the simplex from -// cubit -// -// - -use cubit::f64::procgen::simplex3; -use cubit::f64::types::vec3::{Vec3, Vec3Trait}; -use cubit::f64::types::fixed::{Fixed, FixedTrait, FixedPrint, FixedImpl, ONE}; - -use origami::map::hex::{types::{Direction, HexTile}}; -use origami::map::hex::{hex::{IHexTile, ImplHexTile}}; - -// You can expand this to add more types -mod TileType { - const WATER: u8 = 0; - const LAND: u8 = 1; - const HILL: u8 = 2; - const MOUNTAIN: u8 = 3; -} - -#[generate_trait] -impl ImplTile of ITile { - fn terrain_type(self: HexTile) -> u8 { - let simplex = simplex3::noise( - Vec3Trait::new( - FixedTrait::new_unscaled(self.col.into(), false), - FixedTrait::new_unscaled(self.row.into(), false), - FixedTrait::from_felt(0) - ) - ); - - let mag = simplex.mag; - let one: u64 = ONE.into(); - - // how tiles are defined - if mag > (one * 3 / 4) { - TileType::MOUNTAIN - } else if mag > (one * 2 / 4) { - TileType::HILL - } else if mag > (one * 1 / 4) { - TileType::LAND - } else { - TileType::WATER - } - } - fn check_moveable(self: HexTile) { - assert(self.terrain_type() != TileType::WATER, 'Cannot walk on water'); - } -} - -#[cfg(test)] -mod tests { - use traits::{TryInto, Into}; - use option::OptionTrait; - use debug::PrintTrait; - use super::{Direction, HexTile, ImplHexTile, ITile}; - - - #[test] - fn test_gradient() { - // seems inconsistent - - let mut i = 5; - - let mut tile = ImplHexTile::new(7, 5); - - let neighbors = tile.neighbors(); - - let mut j = 0; - loop { - if (j >= neighbors.len()) { - break; - } - let _n = *neighbors.at(j); - - j += 1; - }; - - i += 1; - } -} diff --git a/examples/market/Scarb.toml b/examples/market/Scarb.toml deleted file mode 100644 index f785542e..00000000 --- a/examples/market/Scarb.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "market" -version = "0.0.0" -description = "Example of defi crate usage." -homepage = "https://github.com/dojoengine/origami/tree/examples/market" - -[dependencies] -cubit.workspace = true -dojo.workspace = true \ No newline at end of file diff --git a/examples/market/src/lib.cairo b/examples/market/src/lib.cairo deleted file mode 100644 index c617df4d..00000000 --- a/examples/market/src/lib.cairo +++ /dev/null @@ -1,17 +0,0 @@ -mod models { - mod cash; - mod item; - mod liquidity; - mod market; -} - -mod systems { - mod liquidity; - mod trade; -} - -#[cfg(test)] -mod tests { - mod setup; - mod trade; -} diff --git a/examples/market/src/models/cash.cairo b/examples/market/src/models/cash.cairo deleted file mode 100644 index d2fbb0ce..00000000 --- a/examples/market/src/models/cash.cairo +++ /dev/null @@ -1,11 +0,0 @@ -// Starknet imports - -use starknet::ContractAddress; - -#[dojo::model] -#[derive(Copy, Drop, Serde)] -struct Cash { - #[key] - player: ContractAddress, - amount: u128, -} diff --git a/examples/market/src/models/item.cairo b/examples/market/src/models/item.cairo deleted file mode 100644 index 7eaa94e6..00000000 --- a/examples/market/src/models/item.cairo +++ /dev/null @@ -1,13 +0,0 @@ -// Starknet imports - -use starknet::ContractAddress; - -#[dojo::model] -#[derive(Copy, Drop, Serde)] -struct Item { - #[key] - player: ContractAddress, - #[key] - item_id: u32, - quantity: u128, -} diff --git a/examples/market/src/models/liquidity.cairo b/examples/market/src/models/liquidity.cairo deleted file mode 100644 index a9add069..00000000 --- a/examples/market/src/models/liquidity.cairo +++ /dev/null @@ -1,53 +0,0 @@ -// Starknet imports - -use starknet::ContractAddress; - -// Dojo imports - -use dojo::database::introspect::{Struct, Ty, Introspect, Member, Layout}; - -// External imports - -use cubit::f128::types::fixed::Fixed; - -// Constants - -const SCALING_FACTOR: u128 = 10000; - -impl IntrospectFixed of Introspect { - #[inline(always)] - fn size() -> Option { - Option::Some(2) - } - - #[inline(always)] - fn layout() -> Layout { - Layout::Fixed(array![128, 1].span()) - } - - #[inline(always)] - fn ty() -> Ty { - Ty::Struct( - Struct { - name: 'Fixed', - attrs: array![].span(), - children: array![ - Member { name: 'mag', attrs: array![].span(), ty: Ty::Primitive('u128') }, - Member { name: 'sign', attrs: array![].span(), ty: Ty::Primitive('bool') }, - ] - .span() - } - ) - } -} - - -#[dojo::model] -#[derive(Copy, Drop, Serde)] -struct Liquidity { - #[key] - player: ContractAddress, - #[key] - item_id: u32, - shares: Fixed, -} diff --git a/examples/market/src/models/market.cairo b/examples/market/src/models/market.cairo deleted file mode 100644 index 26712ce0..00000000 --- a/examples/market/src/models/market.cairo +++ /dev/null @@ -1,421 +0,0 @@ -// External imports - -use cubit::f128::types::fixed::{Fixed, FixedTrait}; - -// Constants - -const SCALING_FACTOR: u128 = 10000; - -#[dojo::model] -#[derive(Copy, Drop, Serde)] -struct Market { - #[key] - item_id: u32, - cash_amount: u128, - item_quantity: u128, -} - -#[generate_trait] -impl MarketImpl of MarketTrait { - fn buy(self: @Market, quantity: u128) -> u128 { - assert(quantity < *self.item_quantity, 'not enough liquidity'); - let (quantity, available, cash) = normalize(quantity, self); - let k = cash * available; - let cost = (k / (available - quantity)) - cash; - cost - } - - fn sell(self: @Market, quantity: u128) -> u128 { - let (quantity, available, cash) = normalize(quantity, self); - let k = cash * available; - let payout = cash - (k / (available + quantity)); - payout - } - - // Get normalized reserve cash amount and item quantity - fn get_reserves(self: @Market) -> (u128, u128) { - let reserve_quantity: u128 = (*self.item_quantity).into() * SCALING_FACTOR; - (*self.cash_amount, reserve_quantity) - } - - // Get the liquidity of the market - // Use cubit fixed point math library to compute the square root of the product of the reserves - fn liquidity(self: @Market) -> Fixed { - // Get normalized reserve cash amount and item quantity - let (reserve_amount, reserve_quantity) = self.get_reserves(); - - // Convert reserve amount to fixed point - let reserve_amount = FixedTrait::new_unscaled(reserve_amount, false); - let reserve_quantity = FixedTrait::new_unscaled(reserve_quantity, false); - - // L = sqrt(X * Y) - (reserve_amount * reserve_quantity).sqrt() - } - - // Check if the market has liquidity - fn has_liquidity(self: @Market) -> bool { - *self.cash_amount > 0 || *self.item_quantity > 0 - } - - // Given some amount of cash, return the equivalent/optimal quantity of items - // based on the reserves in the market - fn quote_quantity(self: @Market, amount: u128) -> u128 { - assert(amount > 0, 'insufficient amount'); - assert(self.has_liquidity(), 'insufficient liquidity'); - - // Get normalized reserve cash amount and item quantity - let (reserve_amount, reserve_quantity) = self.get_reserves(); - - // Convert amount to fixed point - let amount = FixedTrait::new_unscaled(amount, false); - - // Convert reserve amount and quantity to fixed point - let reserve_amount = FixedTrait::new_unscaled(reserve_amount, false); - let reserve_quantity = FixedTrait::new_unscaled(reserve_quantity, false); - - // dy = Y * dx / X - let quantity_optimal = (reserve_quantity * amount) / reserve_amount; - - // Convert from fixed point to u128 - let res: u128 = quantity_optimal.try_into().unwrap(); - res - } - - // Given some quantity of items, return the equivalent/optimal amount of cash - // based on the reserves in the market - fn quote_amount(self: @Market, quantity: u128) -> u128 { - assert(quantity > 0, 'insufficient quantity'); - assert(self.has_liquidity(), 'insufficient liquidity'); - - // Get normalized reserve cash amount and item quantity - let (reserve_amount, reserve_quantity) = self.get_reserves(); - - // Convert reserve amount and quantity to fixed point - let reserve_amount = FixedTrait::new_unscaled(reserve_amount, false); - let reserve_quantity = FixedTrait::new_unscaled(reserve_quantity, false); - - // Normalize quantity - let quantity: u128 = quantity.into() * SCALING_FACTOR; - - // Convert quantity to fixed point - let quantity = FixedTrait::new_unscaled(quantity, false); - - // dx = X * dy / Y - let amount_optimal = (reserve_amount * quantity) / reserve_quantity; - - // Convert from fixed point to u128 - amount_optimal.try_into().unwrap() - } - - // Inner function to add liquidity to the market, computes the optimal amount and quantity - // - // Arguments: - // - // amount: The amount of cash to add to the market - // quantity: The quantity of items to add to the market - // - // Returns: - // - // (amount, quantity): The amount of cash and quantity of items added to the market - fn add_liquidity_inner(self: @Market, amount: u128, quantity: u128) -> (u128, u128) { - // If there is no liquidity, then the amount and quantity are the optimal - if !self.has_liquidity() { - // Ensure that the amount and quantity are greater than zero - assert(amount > 0, 'insufficient amount'); - assert(quantity > 0, 'insufficient quantity'); - (amount, quantity) - } else { - // Given the amount, get optimal quantity to add to the market - let quantity_optimal = self.quote_quantity(amount); - if quantity_optimal <= quantity { - // Add the given amount and optimal quantity to the market - (amount, quantity_optimal) - } else { - let amount_optimal = self.quote_amount(quantity); - // Ensure that the optimal amount is less than or equal to the given amount - assert(amount_optimal <= amount, 'insufficient amount'); - (amount_optimal, quantity) - } - } - } - - // Add liquidity to the market, mints shares for the given amount of liquidity provided - // - // Arguments: - // - // amount: The amount of cash to add to the market - // quantity: The quantity of items to add to the market - // - // Returns: - // - // (amount, quantity, shares): The amount of cash and quantity of items added to the market and - // the shares minted - fn add_liquidity(self: @Market, amount: u128, quantity: u128) -> (u128, u128, Fixed) { - // Compute the amount and quantity to add to the market - let (amount, quantity) = self.add_liquidity_inner(amount, quantity); - // Mint shares for the given amount of liquidity provided - let shares = self.mint_shares(amount, quantity); - (amount, quantity, shares) - } - - // Mint shares for the given amount of liquidity provided - fn mint_shares(self: @Market, amount: u128, quantity: u128) -> Fixed { - // If there is no liquidity, then mint total shares - if !self.has_liquidity() { - let quantity: u128 = quantity.into() * SCALING_FACTOR; - (FixedTrait::new_unscaled(amount, false) * FixedTrait::new_unscaled(quantity, false)) - .sqrt() - } else { - // Convert amount to fixed point - let amount = FixedTrait::new_unscaled(amount, false); - - // Get normalized reserve cash amount and item quantity - let (reserve_amount, _) = self.get_reserves(); - - // Convert reserve amount to fixed point - let reserve_amount = FixedTrait::new_unscaled(reserve_amount, false); - - // Get total liquidity - let liquidity = self.liquidity(); - - // Compute the amount of shares to mint - // S = dx * L/X = dy * L/Y - (amount * liquidity) / reserve_amount - } - } - - // Remove liquidity from the market, return the corresponding amount and quantity payout - // - // Arguments: - // - // shares: The amount of liquidity shares to remove from the market - // - // Returns: - // - // (amount, quantity): The amount of cash and quantity of items removed from the market - fn remove_liquidity(self: @Market, shares: Fixed) -> (u128, u128) { - // Ensure that the market has liquidity - let liquidity = self.liquidity(); - assert(shares <= liquidity, 'insufficient liquidity'); - - // Get normalized reserve cash amount and item quantity - let (reserve_amount, reserve_quantity) = self.get_reserves(); - - // Convert reserve amount and quantity to fixed point - let reserve_amount = FixedTrait::new_unscaled(reserve_amount, false); - let reserve_quantity = FixedTrait::new_unscaled(reserve_quantity, false); - - // Compute the amount and quantity to remove from the market - // dx = S * X / L - let amount = (shares * reserve_amount) / liquidity; - // dy = S * Y / L - let quantity = (shares * reserve_quantity) / liquidity; - - // Convert amount and quantity both from fixed point to u128 and unscaled u128, respectively - (amount.try_into().unwrap(), quantity.try_into().unwrap() / SCALING_FACTOR) - } -} - -fn normalize(quantity: u128, market: @Market) -> (u128, u128, u128) { - let quantity: u128 = quantity.into() * SCALING_FACTOR; - let available: u128 = (*market.item_quantity).into() * SCALING_FACTOR; - (quantity, available, *market.cash_amount) -} - -#[cfg(test)] -mod tests { - // Local imports - - use super::{Market, MarketTrait, SCALING_FACTOR}; - use super::{Fixed, FixedTrait}; - - // Constants - - const TOLERANCE: u128 = 18446744073709550; // 0.001 - - // Helpers - - fn assert_approx_equal(expected: Fixed, actual: Fixed, tolerance: u128) { - let left_bound = expected - FixedTrait::new(tolerance, false); - let right_bound = expected + FixedTrait::new(tolerance, false); - assert(left_bound <= actual && actual <= right_bound, 'Not approx eq'); - } - - #[test] - #[should_panic(expected: ('not enough liquidity',))] - fn test_not_enough_quantity() { - let market = Market { - item_id: 1, cash_amount: SCALING_FACTOR * 1, item_quantity: 1 - }; // pool 1:1 - let _cost = market.buy(10); - } - - #[test] - fn test_market_buy() { - let market = Market { - item_id: 1, cash_amount: SCALING_FACTOR * 1, item_quantity: 10 - }; // pool 1:10 - let cost = market.buy(5); - assert(cost == SCALING_FACTOR * 1, 'wrong cost'); - } - - #[test] - fn test_market_sell() { - let market = Market { - item_id: 1, cash_amount: SCALING_FACTOR * 1, item_quantity: 10 - }; // pool 1:10 - let payout = market.sell(5); - assert(payout == 3334, 'wrong payout'); - } - - #[test] - fn test_market_add_liquidity_no_initial() { - // Without initial liquidity - let market = Market { item_id: 1, cash_amount: 0, item_quantity: 0 }; - - // Add liquidity - let (amount, quantity) = (SCALING_FACTOR * 5, 5); // pool 1:1 - let (amount_add, quantity_add, liquidity_add) = market.add_liquidity(amount, quantity); - - // Assert that the amount and quantity added are the same as the given amount and quantity - // and that the liquidity shares minted are the same as the entire liquidity - assert(amount_add == amount, 'wrong cash amount'); - assert(quantity_add == quantity, 'wrong item quantity'); - - // Convert amount and quantity to fixed point - let amount = FixedTrait::new_unscaled(amount, false); - let quantity: u128 = quantity.into() * SCALING_FACTOR; - let quantity = FixedTrait::new_unscaled(quantity, false); - assert(liquidity_add == (amount * quantity).sqrt(), 'wrong liquidity'); - } - - #[test] - fn test_market_add_liquidity_optimal() { - // With initial liquidity - let market = Market { - item_id: 1, cash_amount: SCALING_FACTOR * 1, item_quantity: 10 - }; // pool 1:10 - let initial_liquidity = market.liquidity(); - - // Add liquidity with the same ratio - let (amount, quantity) = (SCALING_FACTOR * 2, 20); // pool 1:10 - let (amount_add, quantity_add, liquidity_add) = market.add_liquidity(amount, quantity); - - // Assert - assert(amount_add == amount, 'wrong cash amount'); - assert(quantity_add == quantity, 'wrong item quantity'); - - // Get expected amount and convert to fixed point - let expected_amount = FixedTrait::new_unscaled(SCALING_FACTOR * 1 + amount, false); - let expected_quantity: u128 = (10 + quantity).into() * SCALING_FACTOR; - let expected_quantity = FixedTrait::new_unscaled(expected_quantity, false); - - // Compute the expected liquidity shares - let expected_liquidity = FixedTrait::sqrt(expected_amount * expected_quantity); - let final_liquidity = initial_liquidity + liquidity_add; - assert_approx_equal(expected_liquidity, final_liquidity, TOLERANCE); - } - - #[test] - fn test_market_add_liquidity_not_optimal() { - // With initial liquidity - let market = Market { - item_id: 1, cash_amount: SCALING_FACTOR * 1, item_quantity: 10 - }; // pool 1:10 - let initial_liquidity = market.liquidity(); - - // Add liquidity without the same ratio - let (amount, quantity) = (SCALING_FACTOR * 2, 10); // pool 1:5 - - let (amount_add, quantity_add, liquidity_add) = market.add_liquidity(amount, quantity); - - // Assert that the amount added is optimal even though the - // amount originally requested was not - let amount_optimal = SCALING_FACTOR * 1; - assert(amount_add == amount_optimal, 'wrong cash amount'); - assert(quantity_add == quantity, 'wrong item quantity'); - - // Get expected amount and convert to fixed point - let expected_amount = FixedTrait::new_unscaled(SCALING_FACTOR * 1 + amount_add, false); - let expected_quantity: u128 = (10 + quantity).into() * SCALING_FACTOR; - let expected_quantity = FixedTrait::new_unscaled(expected_quantity, false); - - // Get expecteed liquidity - let _expected_liquidity = FixedTrait::sqrt(expected_amount * expected_quantity); - - let _final_liquidity = initial_liquidity + liquidity_add; - // assert_precise(expected_liquidity, final_liquidity.into(), 'wrong liquidity', - // Option::None(())); - } - - #[test] - #[should_panic(expected: ('insufficient amount',))] - fn test_market_add_liquidity_insufficient_amount() { - let market = Market { - item_id: 1, cash_amount: SCALING_FACTOR * 1, item_quantity: 10 - }; // pool 1:10 - // Adding 20 items requires (SCALING_FACTOR * 2) cash amount to maintain the ratio - // Therefore this should fail - let (_amount_add, _quantity_add, _liquidity_add) = market - .add_liquidity(SCALING_FACTOR * 1, 20); - } - - #[test] - fn test_market_remove_liquidity() { - // With initial liquidity - let market = Market { - item_id: 1, cash_amount: SCALING_FACTOR * 2, item_quantity: 20 - }; // pool 1:10 - let initial_liquidity = market.liquidity(); - - // Remove half of the liquidity - let two = FixedTrait::new_unscaled(2, false); - let liquidity_remove = initial_liquidity / two; - - let (amount_remove, quantity_remove) = market.remove_liquidity(liquidity_remove); - - // Assert that the amount and quantity removed are half of the initial amount and quantity - assert(amount_remove == SCALING_FACTOR * 1, 'wrong cash amount'); - assert(quantity_remove == 10, 'wrong item quantity'); - - // Get expected amount and convert to fixed point - let expected_amount = FixedTrait::new_unscaled(SCALING_FACTOR * 2 - amount_remove, false); - let expected_quantity: u128 = (20 - quantity_remove).into() * SCALING_FACTOR; - let expected_quantity = FixedTrait::new_unscaled(expected_quantity, false); - - // Get expecteed liquidity - let _expected_liquidity = FixedTrait::sqrt(expected_amount * expected_quantity); - - let _final_liquidity = initial_liquidity - liquidity_remove; - // assert_precise(expected_liquidity, final_liquidity.into(), 'wrong liquidity', - // Option::None(())); - } - - #[test] - #[should_panic(expected: ('insufficient liquidity',))] - fn test_market_remove_liquidity_no_initial() { - // Without initial liquidity - let market = Market { item_id: 1, cash_amount: 0, item_quantity: 0 }; // pool 1:10 - - // Remove liquidity - let one = FixedTrait::new_unscaled(1, false); - - let (_amount_remove, _quantity_remove) = market.remove_liquidity(one); - } - - #[test] - #[should_panic(expected: ('insufficient liquidity',))] - fn test_market_remove_liquidity_more_than_available() { - // With initial liquidity - let market = Market { - item_id: 1, cash_amount: SCALING_FACTOR * 2, item_quantity: 20 - }; // pool 1:10 - let initial_liquidity = market.liquidity(); - - // Remove twice of the liquidity - let two = FixedTrait::new_unscaled(2, false); - let liquidity_remove = initial_liquidity * two; - - let (_amount_remove, _quantity_remove) = market.remove_liquidity(liquidity_remove); - } -} diff --git a/examples/market/src/systems/liquidity.cairo b/examples/market/src/systems/liquidity.cairo deleted file mode 100644 index e3bd9f82..00000000 --- a/examples/market/src/systems/liquidity.cairo +++ /dev/null @@ -1,121 +0,0 @@ -// Dojo imports - -use dojo::world::IWorldDispatcher; - -// Extenal imports - -use cubit::f128::types::fixed::Fixed; - -#[dojo::interface] -trait ILiquidity { - fn add(ref world: IWorldDispatcher, item_id: u32, amount: u128, quantity: u128); - fn remove(ref world: IWorldDispatcher, item_id: u32, shares: Fixed); -} - -#[dojo::contract] -mod Liquidity { - // Internal imports - - use market::models::{ - item::Item, cash::Cash, liquidity::Liquidity, market::{Market, MarketTrait} - }; - - // Local imports - - use super::Fixed; - use super::ILiquidity; - - #[abi(embed_v0)] - impl LiquidityImpl of ILiquidity { - fn add(ref 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(ref 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 - }) - ); - } - } -} diff --git a/examples/market/src/systems/trade.cairo b/examples/market/src/systems/trade.cairo deleted file mode 100644 index 0cb401c0..00000000 --- a/examples/market/src/systems/trade.cairo +++ /dev/null @@ -1,87 +0,0 @@ -// Dojo imports - -use dojo::world::IWorldDispatcher; - -#[dojo::interface] -trait ITrade { - fn buy(ref world: IWorldDispatcher, item_id: u32, quantity: u128); - fn sell(ref world: IWorldDispatcher, item_id: u32, quantity: u128); -} - -#[dojo::contract] -mod Trade { - // Internal imports - - use market::models::{item::Item, cash::Cash, market::{Market, MarketTrait}}; - - // Local imports - - use super::ITrade; - - #[abi(embed_v0)] - impl TradeImpl of ITrade { - fn buy(ref 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(ref 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 }) - ); - } - } -} diff --git a/examples/market/src/tests/setup.cairo b/examples/market/src/tests/setup.cairo deleted file mode 100644 index be384ca3..00000000 --- a/examples/market/src/tests/setup.cairo +++ /dev/null @@ -1,41 +0,0 @@ -// Starknet imports - -use starknet::ContractAddress; - -// Dojo imports - -use dojo::world::{IWorldDispatcherTrait, IWorldDispatcher}; -use dojo::test_utils::{spawn_test_world, deploy_contract}; - -// Internal imports - -use market::models::cash::{cash, Cash}; -use market::models::item::{item, Item}; -use market::models::liquidity::{liquidity, Liquidity}; -use market::models::market::{market as market_model, Market}; -use market::systems::liquidity::{Liquidity as liquidity_actions}; -use market::systems::trade::{Trade as trade_actions}; - -#[derive(Drop)] -struct Systems { - liquidity: ContractAddress, - trade: ContractAddress, -} - -fn spawn_market() -> (IWorldDispatcher, Systems) { - // [Setup] World - let mut models = array::ArrayTrait::new(); - models.append(cash::TEST_CLASS_HASH); - models.append(item::TEST_CLASS_HASH); - models.append(liquidity::TEST_CLASS_HASH); - models.append(market_model::TEST_CLASS_HASH); - let world = spawn_test_world(models); - - // [Setup] Systems - let liquidity_address = deploy_contract(liquidity_actions::TEST_CLASS_HASH, array![].span()); - let trade_address = deploy_contract(trade_actions::TEST_CLASS_HASH, array![].span()); - let systems = Systems { liquidity: liquidity_address, trade: trade_address, }; - - // [Return] - (world, systems) -} diff --git a/examples/market/src/tests/trade.cairo b/examples/market/src/tests/trade.cairo deleted file mode 100644 index 4ae8ae8d..00000000 --- a/examples/market/src/tests/trade.cairo +++ /dev/null @@ -1,21 +0,0 @@ -// Core imports - -use debug::PrintTrait; - -// Dojo imports - -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - -// Internal imports - -use market::models::cash::Cash; -use market::models::item::Item; -use market::models::liquidity::Liquidity; -use market::models::market::{Market, MarketTrait}; -use market::tests::{setup, setup::Systems}; - -#[test] -fn test_market_spawn() { - // [Setup] - let (_world, _systems) = setup::spawn_market(); -} diff --git a/examples/matchmaker/Scarb.toml b/examples/matchmaker/Scarb.toml deleted file mode 100644 index 48e20b0e..00000000 --- a/examples/matchmaker/Scarb.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "matchmaker" -version = "0.0.0" -description = "Example of elo rating crate usage." -homepage = "https://github.com/dojoengine/origami/tree/examples/matchmaker" - -[dependencies] -dojo.workspace = true -origami.workspace = true \ No newline at end of file diff --git a/examples/matchmaker/src/constants.cairo b/examples/matchmaker/src/constants.cairo deleted file mode 100644 index 42b296f7..00000000 --- a/examples/matchmaker/src/constants.cairo +++ /dev/null @@ -1,279 +0,0 @@ -// ELO - -const DEFAULT_K_FACTOR: u8 = 20; -const DEFAULT_RATING: u32 = 1000; - -// Leagues - -const LEAGUE_SIZE: u8 = 20; -const LEAGUE_COUNT: u8 = 17; -const LEAGUE_MIN_THRESHOLD: u32 = 1000; - -// World - -fn WORLD() -> starknet::ContractAddress { - starknet::contract_address_const::<'WORLD'>() -} - -// Constants - -fn ZERO() -> starknet::ContractAddress { - starknet::contract_address_const::<0>() -} - -// Bitmap - -const TWO_POW_0: u256 = 0x1; -const TWO_POW_1: u256 = 0x2; -const TWO_POW_2: u256 = 0x4; -const TWO_POW_3: u256 = 0x8; -const TWO_POW_4: u256 = 0x10; -const TWO_POW_5: u256 = 0x20; -const TWO_POW_6: u256 = 0x40; -const TWO_POW_7: u256 = 0x80; -const TWO_POW_8: u256 = 0x100; -const TWO_POW_9: u256 = 0x200; -const TWO_POW_10: u256 = 0x400; -const TWO_POW_11: u256 = 0x800; -const TWO_POW_12: u256 = 0x1000; -const TWO_POW_13: u256 = 0x2000; -const TWO_POW_14: u256 = 0x4000; -const TWO_POW_15: u256 = 0x8000; -const TWO_POW_16: u256 = 0x10000; -const TWO_POW_17: u256 = 0x20000; -const TWO_POW_18: u256 = 0x40000; -const TWO_POW_19: u256 = 0x80000; -const TWO_POW_20: u256 = 0x100000; -const TWO_POW_21: u256 = 0x200000; -const TWO_POW_22: u256 = 0x400000; -const TWO_POW_23: u256 = 0x800000; -const TWO_POW_24: u256 = 0x1000000; -const TWO_POW_25: u256 = 0x2000000; -const TWO_POW_26: u256 = 0x4000000; -const TWO_POW_27: u256 = 0x8000000; -const TWO_POW_28: u256 = 0x10000000; -const TWO_POW_29: u256 = 0x20000000; -const TWO_POW_30: u256 = 0x40000000; -const TWO_POW_31: u256 = 0x80000000; -const TWO_POW_32: u256 = 0x100000000; -const TWO_POW_33: u256 = 0x200000000; -const TWO_POW_34: u256 = 0x400000000; -const TWO_POW_35: u256 = 0x800000000; -const TWO_POW_36: u256 = 0x1000000000; -const TWO_POW_37: u256 = 0x2000000000; -const TWO_POW_38: u256 = 0x4000000000; -const TWO_POW_39: u256 = 0x8000000000; -const TWO_POW_40: u256 = 0x10000000000; -const TWO_POW_41: u256 = 0x20000000000; -const TWO_POW_42: u256 = 0x40000000000; -const TWO_POW_43: u256 = 0x80000000000; -const TWO_POW_44: u256 = 0x100000000000; -const TWO_POW_45: u256 = 0x200000000000; -const TWO_POW_46: u256 = 0x400000000000; -const TWO_POW_47: u256 = 0x800000000000; -const TWO_POW_48: u256 = 0x1000000000000; -const TWO_POW_49: u256 = 0x2000000000000; -const TWO_POW_50: u256 = 0x4000000000000; -const TWO_POW_51: u256 = 0x8000000000000; -const TWO_POW_52: u256 = 0x10000000000000; -const TWO_POW_53: u256 = 0x20000000000000; -const TWO_POW_54: u256 = 0x40000000000000; -const TWO_POW_55: u256 = 0x80000000000000; -const TWO_POW_56: u256 = 0x100000000000000; -const TWO_POW_57: u256 = 0x200000000000000; -const TWO_POW_58: u256 = 0x400000000000000; -const TWO_POW_59: u256 = 0x800000000000000; -const TWO_POW_60: u256 = 0x1000000000000000; -const TWO_POW_61: u256 = 0x2000000000000000; -const TWO_POW_62: u256 = 0x4000000000000000; -const TWO_POW_63: u256 = 0x8000000000000000; -const TWO_POW_64: u256 = 0x10000000000000000; -const TWO_POW_65: u256 = 0x20000000000000000; -const TWO_POW_66: u256 = 0x40000000000000000; -const TWO_POW_67: u256 = 0x80000000000000000; -const TWO_POW_68: u256 = 0x100000000000000000; -const TWO_POW_69: u256 = 0x200000000000000000; -const TWO_POW_70: u256 = 0x400000000000000000; -const TWO_POW_71: u256 = 0x800000000000000000; -const TWO_POW_72: u256 = 0x1000000000000000000; -const TWO_POW_73: u256 = 0x2000000000000000000; -const TWO_POW_74: u256 = 0x4000000000000000000; -const TWO_POW_75: u256 = 0x8000000000000000000; -const TWO_POW_76: u256 = 0x10000000000000000000; -const TWO_POW_77: u256 = 0x20000000000000000000; -const TWO_POW_78: u256 = 0x40000000000000000000; -const TWO_POW_79: u256 = 0x80000000000000000000; -const TWO_POW_80: u256 = 0x100000000000000000000; -const TWO_POW_81: u256 = 0x200000000000000000000; -const TWO_POW_82: u256 = 0x400000000000000000000; -const TWO_POW_83: u256 = 0x800000000000000000000; -const TWO_POW_84: u256 = 0x1000000000000000000000; -const TWO_POW_85: u256 = 0x2000000000000000000000; -const TWO_POW_86: u256 = 0x4000000000000000000000; -const TWO_POW_87: u256 = 0x8000000000000000000000; -const TWO_POW_88: u256 = 0x10000000000000000000000; -const TWO_POW_89: u256 = 0x20000000000000000000000; -const TWO_POW_90: u256 = 0x40000000000000000000000; -const TWO_POW_91: u256 = 0x80000000000000000000000; -const TWO_POW_92: u256 = 0x100000000000000000000000; -const TWO_POW_93: u256 = 0x200000000000000000000000; -const TWO_POW_94: u256 = 0x400000000000000000000000; -const TWO_POW_95: u256 = 0x800000000000000000000000; -const TWO_POW_96: u256 = 0x1000000000000000000000000; -const TWO_POW_97: u256 = 0x2000000000000000000000000; -const TWO_POW_98: u256 = 0x4000000000000000000000000; -const TWO_POW_99: u256 = 0x8000000000000000000000000; -const TWO_POW_100: u256 = 0x10000000000000000000000000; -const TWO_POW_101: u256 = 0x20000000000000000000000000; -const TWO_POW_102: u256 = 0x40000000000000000000000000; -const TWO_POW_103: u256 = 0x80000000000000000000000000; -const TWO_POW_104: u256 = 0x100000000000000000000000000; -const TWO_POW_105: u256 = 0x200000000000000000000000000; -const TWO_POW_106: u256 = 0x400000000000000000000000000; -const TWO_POW_107: u256 = 0x800000000000000000000000000; -const TWO_POW_108: u256 = 0x1000000000000000000000000000; -const TWO_POW_109: u256 = 0x2000000000000000000000000000; -const TWO_POW_110: u256 = 0x4000000000000000000000000000; -const TWO_POW_111: u256 = 0x8000000000000000000000000000; -const TWO_POW_112: u256 = 0x10000000000000000000000000000; -const TWO_POW_113: u256 = 0x20000000000000000000000000000; -const TWO_POW_114: u256 = 0x40000000000000000000000000000; -const TWO_POW_115: u256 = 0x80000000000000000000000000000; -const TWO_POW_116: u256 = 0x100000000000000000000000000000; -const TWO_POW_117: u256 = 0x200000000000000000000000000000; -const TWO_POW_118: u256 = 0x400000000000000000000000000000; -const TWO_POW_119: u256 = 0x800000000000000000000000000000; -const TWO_POW_120: u256 = 0x1000000000000000000000000000000; -const TWO_POW_121: u256 = 0x2000000000000000000000000000000; -const TWO_POW_122: u256 = 0x4000000000000000000000000000000; -const TWO_POW_123: u256 = 0x8000000000000000000000000000000; -const TWO_POW_124: u256 = 0x10000000000000000000000000000000; -const TWO_POW_125: u256 = 0x20000000000000000000000000000000; -const TWO_POW_126: u256 = 0x40000000000000000000000000000000; -const TWO_POW_127: u256 = 0x80000000000000000000000000000000; -const TWO_POW_128: u256 = 0x100000000000000000000000000000000; -const TWO_POW_129: u256 = 0x200000000000000000000000000000000; -const TWO_POW_130: u256 = 0x400000000000000000000000000000000; -const TWO_POW_131: u256 = 0x800000000000000000000000000000000; -const TWO_POW_132: u256 = 0x1000000000000000000000000000000000; -const TWO_POW_133: u256 = 0x2000000000000000000000000000000000; -const TWO_POW_134: u256 = 0x4000000000000000000000000000000000; -const TWO_POW_135: u256 = 0x8000000000000000000000000000000000; -const TWO_POW_136: u256 = 0x10000000000000000000000000000000000; -const TWO_POW_137: u256 = 0x20000000000000000000000000000000000; -const TWO_POW_138: u256 = 0x40000000000000000000000000000000000; -const TWO_POW_139: u256 = 0x80000000000000000000000000000000000; -const TWO_POW_140: u256 = 0x100000000000000000000000000000000000; -const TWO_POW_141: u256 = 0x200000000000000000000000000000000000; -const TWO_POW_142: u256 = 0x400000000000000000000000000000000000; -const TWO_POW_143: u256 = 0x800000000000000000000000000000000000; -const TWO_POW_144: u256 = 0x1000000000000000000000000000000000000; -const TWO_POW_145: u256 = 0x2000000000000000000000000000000000000; -const TWO_POW_146: u256 = 0x4000000000000000000000000000000000000; -const TWO_POW_147: u256 = 0x8000000000000000000000000000000000000; -const TWO_POW_148: u256 = 0x10000000000000000000000000000000000000; -const TWO_POW_149: u256 = 0x20000000000000000000000000000000000000; -const TWO_POW_150: u256 = 0x40000000000000000000000000000000000000; -const TWO_POW_151: u256 = 0x80000000000000000000000000000000000000; -const TWO_POW_152: u256 = 0x100000000000000000000000000000000000000; -const TWO_POW_153: u256 = 0x200000000000000000000000000000000000000; -const TWO_POW_154: u256 = 0x400000000000000000000000000000000000000; -const TWO_POW_155: u256 = 0x800000000000000000000000000000000000000; -const TWO_POW_156: u256 = 0x1000000000000000000000000000000000000000; -const TWO_POW_157: u256 = 0x2000000000000000000000000000000000000000; -const TWO_POW_158: u256 = 0x4000000000000000000000000000000000000000; -const TWO_POW_159: u256 = 0x8000000000000000000000000000000000000000; -const TWO_POW_160: u256 = 0x10000000000000000000000000000000000000000; -const TWO_POW_161: u256 = 0x20000000000000000000000000000000000000000; -const TWO_POW_162: u256 = 0x40000000000000000000000000000000000000000; -const TWO_POW_163: u256 = 0x80000000000000000000000000000000000000000; -const TWO_POW_164: u256 = 0x100000000000000000000000000000000000000000; -const TWO_POW_165: u256 = 0x200000000000000000000000000000000000000000; -const TWO_POW_166: u256 = 0x400000000000000000000000000000000000000000; -const TWO_POW_167: u256 = 0x800000000000000000000000000000000000000000; -const TWO_POW_168: u256 = 0x1000000000000000000000000000000000000000000; -const TWO_POW_169: u256 = 0x2000000000000000000000000000000000000000000; -const TWO_POW_170: u256 = 0x4000000000000000000000000000000000000000000; -const TWO_POW_171: u256 = 0x8000000000000000000000000000000000000000000; -const TWO_POW_172: u256 = 0x10000000000000000000000000000000000000000000; -const TWO_POW_173: u256 = 0x20000000000000000000000000000000000000000000; -const TWO_POW_174: u256 = 0x40000000000000000000000000000000000000000000; -const TWO_POW_175: u256 = 0x80000000000000000000000000000000000000000000; -const TWO_POW_176: u256 = 0x100000000000000000000000000000000000000000000; -const TWO_POW_177: u256 = 0x200000000000000000000000000000000000000000000; -const TWO_POW_178: u256 = 0x400000000000000000000000000000000000000000000; -const TWO_POW_179: u256 = 0x800000000000000000000000000000000000000000000; -const TWO_POW_180: u256 = 0x1000000000000000000000000000000000000000000000; -const TWO_POW_181: u256 = 0x2000000000000000000000000000000000000000000000; -const TWO_POW_182: u256 = 0x4000000000000000000000000000000000000000000000; -const TWO_POW_183: u256 = 0x8000000000000000000000000000000000000000000000; -const TWO_POW_184: u256 = 0x10000000000000000000000000000000000000000000000; -const TWO_POW_185: u256 = 0x20000000000000000000000000000000000000000000000; -const TWO_POW_186: u256 = 0x40000000000000000000000000000000000000000000000; -const TWO_POW_187: u256 = 0x80000000000000000000000000000000000000000000000; -const TWO_POW_188: u256 = 0x100000000000000000000000000000000000000000000000; -const TWO_POW_189: u256 = 0x200000000000000000000000000000000000000000000000; -const TWO_POW_190: u256 = 0x400000000000000000000000000000000000000000000000; -const TWO_POW_191: u256 = 0x800000000000000000000000000000000000000000000000; -const TWO_POW_192: u256 = 0x1000000000000000000000000000000000000000000000000; -const TWO_POW_193: u256 = 0x2000000000000000000000000000000000000000000000000; -const TWO_POW_194: u256 = 0x4000000000000000000000000000000000000000000000000; -const TWO_POW_195: u256 = 0x8000000000000000000000000000000000000000000000000; -const TWO_POW_196: u256 = 0x10000000000000000000000000000000000000000000000000; -const TWO_POW_197: u256 = 0x20000000000000000000000000000000000000000000000000; -const TWO_POW_198: u256 = 0x40000000000000000000000000000000000000000000000000; -const TWO_POW_199: u256 = 0x80000000000000000000000000000000000000000000000000; -const TWO_POW_200: u256 = 0x100000000000000000000000000000000000000000000000000; -const TWO_POW_201: u256 = 0x200000000000000000000000000000000000000000000000000; -const TWO_POW_202: u256 = 0x400000000000000000000000000000000000000000000000000; -const TWO_POW_203: u256 = 0x800000000000000000000000000000000000000000000000000; -const TWO_POW_204: u256 = 0x1000000000000000000000000000000000000000000000000000; -const TWO_POW_205: u256 = 0x2000000000000000000000000000000000000000000000000000; -const TWO_POW_206: u256 = 0x4000000000000000000000000000000000000000000000000000; -const TWO_POW_207: u256 = 0x8000000000000000000000000000000000000000000000000000; -const TWO_POW_208: u256 = 0x10000000000000000000000000000000000000000000000000000; -const TWO_POW_209: u256 = 0x20000000000000000000000000000000000000000000000000000; -const TWO_POW_210: u256 = 0x40000000000000000000000000000000000000000000000000000; -const TWO_POW_211: u256 = 0x80000000000000000000000000000000000000000000000000000; -const TWO_POW_212: u256 = 0x100000000000000000000000000000000000000000000000000000; -const TWO_POW_213: u256 = 0x200000000000000000000000000000000000000000000000000000; -const TWO_POW_214: u256 = 0x400000000000000000000000000000000000000000000000000000; -const TWO_POW_215: u256 = 0x800000000000000000000000000000000000000000000000000000; -const TWO_POW_216: u256 = 0x1000000000000000000000000000000000000000000000000000000; -const TWO_POW_217: u256 = 0x2000000000000000000000000000000000000000000000000000000; -const TWO_POW_218: u256 = 0x4000000000000000000000000000000000000000000000000000000; -const TWO_POW_219: u256 = 0x8000000000000000000000000000000000000000000000000000000; -const TWO_POW_220: u256 = 0x10000000000000000000000000000000000000000000000000000000; -const TWO_POW_221: u256 = 0x20000000000000000000000000000000000000000000000000000000; -const TWO_POW_222: u256 = 0x40000000000000000000000000000000000000000000000000000000; -const TWO_POW_223: u256 = 0x80000000000000000000000000000000000000000000000000000000; -const TWO_POW_224: u256 = 0x100000000000000000000000000000000000000000000000000000000; -const TWO_POW_225: u256 = 0x200000000000000000000000000000000000000000000000000000000; -const TWO_POW_226: u256 = 0x400000000000000000000000000000000000000000000000000000000; -const TWO_POW_227: u256 = 0x800000000000000000000000000000000000000000000000000000000; -const TWO_POW_228: u256 = 0x1000000000000000000000000000000000000000000000000000000000; -const TWO_POW_229: u256 = 0x2000000000000000000000000000000000000000000000000000000000; -const TWO_POW_230: u256 = 0x4000000000000000000000000000000000000000000000000000000000; -const TWO_POW_231: u256 = 0x8000000000000000000000000000000000000000000000000000000000; -const TWO_POW_232: u256 = 0x10000000000000000000000000000000000000000000000000000000000; -const TWO_POW_233: u256 = 0x20000000000000000000000000000000000000000000000000000000000; -const TWO_POW_234: u256 = 0x40000000000000000000000000000000000000000000000000000000000; -const TWO_POW_235: u256 = 0x80000000000000000000000000000000000000000000000000000000000; -const TWO_POW_236: u256 = 0x100000000000000000000000000000000000000000000000000000000000; -const TWO_POW_237: u256 = 0x200000000000000000000000000000000000000000000000000000000000; -const TWO_POW_238: u256 = 0x400000000000000000000000000000000000000000000000000000000000; -const TWO_POW_239: u256 = 0x800000000000000000000000000000000000000000000000000000000000; -const TWO_POW_240: u256 = 0x1000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_241: u256 = 0x2000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_242: u256 = 0x4000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_243: u256 = 0x8000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_244: u256 = 0x10000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_245: u256 = 0x20000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_246: u256 = 0x40000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_247: u256 = 0x80000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_248: u256 = 0x100000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_249: u256 = 0x200000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_250: u256 = 0x400000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_251: u256 = 0x800000000000000000000000000000000000000000000000000000000000000; -const TWO_POW_252: u256 = 0x1000000000000000000000000000000000000000000000000000000000000000; - diff --git a/examples/matchmaker/src/helpers/bitmap.cairo b/examples/matchmaker/src/helpers/bitmap.cairo deleted file mode 100644 index c1764852..00000000 --- a/examples/matchmaker/src/helpers/bitmap.cairo +++ /dev/null @@ -1,490 +0,0 @@ -// Core imports - -use core::integer::BoundedInt; -use core::debug::PrintTrait; - -// Internal imports - -use matchmaker::constants; - -// Errors - -mod errors { - const INVALID_INDEX: felt252 = 'Bitmap: invalid index'; -} - -#[generate_trait] -impl Bitmap of BitmapTrait { - #[inline(always)] - fn get_bit_at(bitmap: u256, index: felt252) -> bool { - let mask = Self::two_pow(index); - bitmap & mask == mask - } - - #[inline(always)] - fn set_bit_at(bitmap: u256, index: felt252, value: bool) -> u256 { - let mask = Self::two_pow(index); - if value { - bitmap | mask - } else { - bitmap & (BoundedInt::max() - mask) - } - } - - /// The index of the nearest significant bit to the index of the number, - /// where the least significant bit is at index 0 and the most significant bit is at index 255 - /// # Arguments - /// * `x` - The value for which to compute the most significant bit, must be greater than 0. - /// * `s` - The index for which to start the search. - /// # Returns - /// * The index of the nearest significant bit - #[inline(always)] - fn nearest_significant_bit(x: u256, s: u8) -> Option:: { - let lower_mask = Self::set_bit_at(0, (s + 1).into(), true) - 1; - let lower = Self::most_significant_bit(x & lower_mask); - let upper_mask = ~(lower_mask / 2); - let upper = Self::least_significant_bit(x & upper_mask); - match (lower, upper) { - ( - Option::Some(l), Option::Some(u) - ) => { if s - l < u - s { - Option::Some(l) - } else { - Option::Some(u) - } }, - (Option::Some(l), Option::None) => Option::Some(l), - (Option::None, Option::Some(u)) => Option::Some(u), - (Option::None, Option::None) => Option::None, - } - } - - /// The index of the most significant bit of the number, - /// where the least significant bit is at index 0 and the most significant bit is at index 255 - /// # Arguments * `x` - The value for which to compute the most significant bit, must be greater - /// than 0. - /// # Returns - /// * The index of the most significant bit - #[inline(always)] - fn most_significant_bit(mut x: u256) -> Option { - if x == 0 { - return Option::None; - } - let mut r: u8 = 0; - - if x >= 0x100000000000000000000000000000000 { - x /= 0x100000000000000000000000000000000; - r += 128; - } - if x >= 0x10000000000000000 { - x /= 0x10000000000000000; - r += 64; - } - if x >= 0x100000000 { - x /= 0x100000000; - r += 32; - } - if x >= 0x10000 { - x /= 0x10000; - r += 16; - } - if x >= 0x100 { - x /= 0x100; - r += 8; - } - if x >= 0x10 { - x /= 0x10; - r += 4; - } - if x >= 0x4 { - x /= 0x4; - r += 2; - } - if x >= 0x2 { - r += 1; - } - Option::Some(r) - } - - /// The index of the least significant bit of the number, - /// where the least significant bit is at index 0 and the most significant bit is at index 255 - /// # Arguments * `x` - The value for which to compute the least significant bit, must be - /// greater than 0. - /// # Returns - /// * The index of the least significant bit - #[inline(always)] - fn least_significant_bit(mut x: u256) -> Option { - if x == 0 { - return Option::None; - } - let mut r: u8 = 255; - - if (x & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) > 0 { - r -= 128; - } else { - x /= 0x100000000000000000000000000000000; - } - if (x & 0xFFFFFFFFFFFFFFFF) > 0 { - r -= 64; - } else { - x /= 0x10000000000000000; - } - if (x & 0xFFFFFFFF) > 0 { - r -= 32; - } else { - x /= 0x100000000; - } - if (x & 0xFFFF) > 0 { - r -= 16; - } else { - x /= 0x10000; - } - if (x & 0xFF) > 0 { - r -= 8; - } else { - x /= 0x100; - } - if (x & 0xF) > 0 { - r -= 4; - } else { - x /= 0x10; - } - if (x & 0x3) > 0 { - r -= 2; - } else { - x /= 0x4; - } - if (x & 0x1) > 0 { - r -= 1; - } - Option::Some(r) - } - - #[inline(always)] - fn two_pow(exponent: felt252) -> u256 { - match exponent { - 0 => constants::TWO_POW_0, - 1 => constants::TWO_POW_1, - 2 => constants::TWO_POW_2, - 3 => constants::TWO_POW_3, - 4 => constants::TWO_POW_4, - 5 => constants::TWO_POW_5, - 6 => constants::TWO_POW_6, - 7 => constants::TWO_POW_7, - 8 => constants::TWO_POW_8, - 9 => constants::TWO_POW_9, - 10 => constants::TWO_POW_10, - 11 => constants::TWO_POW_11, - 12 => constants::TWO_POW_12, - 13 => constants::TWO_POW_13, - 14 => constants::TWO_POW_14, - 15 => constants::TWO_POW_15, - 16 => constants::TWO_POW_16, - 17 => constants::TWO_POW_17, - 18 => constants::TWO_POW_18, - 19 => constants::TWO_POW_19, - 20 => constants::TWO_POW_20, - 21 => constants::TWO_POW_21, - 22 => constants::TWO_POW_22, - 23 => constants::TWO_POW_23, - 24 => constants::TWO_POW_24, - 25 => constants::TWO_POW_25, - 26 => constants::TWO_POW_26, - 27 => constants::TWO_POW_27, - 28 => constants::TWO_POW_28, - 29 => constants::TWO_POW_29, - 30 => constants::TWO_POW_30, - 31 => constants::TWO_POW_31, - 32 => constants::TWO_POW_32, - 33 => constants::TWO_POW_33, - 34 => constants::TWO_POW_34, - 35 => constants::TWO_POW_35, - 36 => constants::TWO_POW_36, - 37 => constants::TWO_POW_37, - 38 => constants::TWO_POW_38, - 39 => constants::TWO_POW_39, - 40 => constants::TWO_POW_40, - 41 => constants::TWO_POW_41, - 42 => constants::TWO_POW_42, - 43 => constants::TWO_POW_43, - 44 => constants::TWO_POW_44, - 45 => constants::TWO_POW_45, - 46 => constants::TWO_POW_46, - 47 => constants::TWO_POW_47, - 48 => constants::TWO_POW_48, - 49 => constants::TWO_POW_49, - 50 => constants::TWO_POW_50, - 51 => constants::TWO_POW_51, - 52 => constants::TWO_POW_52, - 53 => constants::TWO_POW_53, - 54 => constants::TWO_POW_54, - 55 => constants::TWO_POW_55, - 56 => constants::TWO_POW_56, - 57 => constants::TWO_POW_57, - 58 => constants::TWO_POW_58, - 59 => constants::TWO_POW_59, - 60 => constants::TWO_POW_60, - 61 => constants::TWO_POW_61, - 62 => constants::TWO_POW_62, - 63 => constants::TWO_POW_63, - 64 => constants::TWO_POW_64, - 65 => constants::TWO_POW_65, - 66 => constants::TWO_POW_66, - 67 => constants::TWO_POW_67, - 68 => constants::TWO_POW_68, - 69 => constants::TWO_POW_69, - 70 => constants::TWO_POW_70, - 71 => constants::TWO_POW_71, - 72 => constants::TWO_POW_72, - 73 => constants::TWO_POW_73, - 74 => constants::TWO_POW_74, - 75 => constants::TWO_POW_75, - 76 => constants::TWO_POW_76, - 77 => constants::TWO_POW_77, - 78 => constants::TWO_POW_78, - 79 => constants::TWO_POW_79, - 80 => constants::TWO_POW_80, - 81 => constants::TWO_POW_81, - 82 => constants::TWO_POW_82, - 83 => constants::TWO_POW_83, - 84 => constants::TWO_POW_84, - 85 => constants::TWO_POW_85, - 86 => constants::TWO_POW_86, - 87 => constants::TWO_POW_87, - 88 => constants::TWO_POW_88, - 89 => constants::TWO_POW_89, - 90 => constants::TWO_POW_90, - 91 => constants::TWO_POW_91, - 92 => constants::TWO_POW_92, - 93 => constants::TWO_POW_93, - 94 => constants::TWO_POW_94, - 95 => constants::TWO_POW_95, - 96 => constants::TWO_POW_96, - 97 => constants::TWO_POW_97, - 98 => constants::TWO_POW_98, - 99 => constants::TWO_POW_99, - 100 => constants::TWO_POW_100, - 101 => constants::TWO_POW_101, - 102 => constants::TWO_POW_102, - 103 => constants::TWO_POW_103, - 104 => constants::TWO_POW_104, - 105 => constants::TWO_POW_105, - 106 => constants::TWO_POW_106, - 107 => constants::TWO_POW_107, - 108 => constants::TWO_POW_108, - 109 => constants::TWO_POW_109, - 110 => constants::TWO_POW_110, - 111 => constants::TWO_POW_111, - 112 => constants::TWO_POW_112, - 113 => constants::TWO_POW_113, - 114 => constants::TWO_POW_114, - 115 => constants::TWO_POW_115, - 116 => constants::TWO_POW_116, - 117 => constants::TWO_POW_117, - 118 => constants::TWO_POW_118, - 119 => constants::TWO_POW_119, - 120 => constants::TWO_POW_120, - 121 => constants::TWO_POW_121, - 122 => constants::TWO_POW_122, - 123 => constants::TWO_POW_123, - 124 => constants::TWO_POW_124, - 125 => constants::TWO_POW_125, - 126 => constants::TWO_POW_126, - 127 => constants::TWO_POW_127, - 128 => constants::TWO_POW_128, - 129 => constants::TWO_POW_129, - 130 => constants::TWO_POW_130, - 131 => constants::TWO_POW_131, - 132 => constants::TWO_POW_132, - 133 => constants::TWO_POW_133, - 134 => constants::TWO_POW_134, - 135 => constants::TWO_POW_135, - 136 => constants::TWO_POW_136, - 137 => constants::TWO_POW_137, - 138 => constants::TWO_POW_138, - 139 => constants::TWO_POW_139, - 140 => constants::TWO_POW_140, - 141 => constants::TWO_POW_141, - 142 => constants::TWO_POW_142, - 143 => constants::TWO_POW_143, - 144 => constants::TWO_POW_144, - 145 => constants::TWO_POW_145, - 146 => constants::TWO_POW_146, - 147 => constants::TWO_POW_147, - 148 => constants::TWO_POW_148, - 149 => constants::TWO_POW_149, - 150 => constants::TWO_POW_150, - 151 => constants::TWO_POW_151, - 152 => constants::TWO_POW_152, - 153 => constants::TWO_POW_153, - 154 => constants::TWO_POW_154, - 155 => constants::TWO_POW_155, - 156 => constants::TWO_POW_156, - 157 => constants::TWO_POW_157, - 158 => constants::TWO_POW_158, - 159 => constants::TWO_POW_159, - 160 => constants::TWO_POW_160, - 161 => constants::TWO_POW_161, - 162 => constants::TWO_POW_162, - 163 => constants::TWO_POW_163, - 164 => constants::TWO_POW_164, - 165 => constants::TWO_POW_165, - 166 => constants::TWO_POW_166, - 167 => constants::TWO_POW_167, - 168 => constants::TWO_POW_168, - 169 => constants::TWO_POW_169, - 170 => constants::TWO_POW_170, - 171 => constants::TWO_POW_171, - 172 => constants::TWO_POW_172, - 173 => constants::TWO_POW_173, - 174 => constants::TWO_POW_174, - 175 => constants::TWO_POW_175, - 176 => constants::TWO_POW_176, - 177 => constants::TWO_POW_177, - 178 => constants::TWO_POW_178, - 179 => constants::TWO_POW_179, - 180 => constants::TWO_POW_180, - 181 => constants::TWO_POW_181, - 182 => constants::TWO_POW_182, - 183 => constants::TWO_POW_183, - 184 => constants::TWO_POW_184, - 185 => constants::TWO_POW_185, - 186 => constants::TWO_POW_186, - 187 => constants::TWO_POW_187, - 188 => constants::TWO_POW_188, - 189 => constants::TWO_POW_189, - 190 => constants::TWO_POW_190, - 191 => constants::TWO_POW_191, - 192 => constants::TWO_POW_192, - 193 => constants::TWO_POW_193, - 194 => constants::TWO_POW_194, - 195 => constants::TWO_POW_195, - 196 => constants::TWO_POW_196, - 197 => constants::TWO_POW_197, - 198 => constants::TWO_POW_198, - 199 => constants::TWO_POW_199, - 200 => constants::TWO_POW_200, - 201 => constants::TWO_POW_201, - 202 => constants::TWO_POW_202, - 203 => constants::TWO_POW_203, - 204 => constants::TWO_POW_204, - 205 => constants::TWO_POW_205, - 206 => constants::TWO_POW_206, - 207 => constants::TWO_POW_207, - 208 => constants::TWO_POW_208, - 209 => constants::TWO_POW_209, - 210 => constants::TWO_POW_210, - 211 => constants::TWO_POW_211, - 212 => constants::TWO_POW_212, - 213 => constants::TWO_POW_213, - 214 => constants::TWO_POW_214, - 215 => constants::TWO_POW_215, - 216 => constants::TWO_POW_216, - 217 => constants::TWO_POW_217, - 218 => constants::TWO_POW_218, - 219 => constants::TWO_POW_219, - 220 => constants::TWO_POW_220, - 221 => constants::TWO_POW_221, - 222 => constants::TWO_POW_222, - 223 => constants::TWO_POW_223, - 224 => constants::TWO_POW_224, - 225 => constants::TWO_POW_225, - 226 => constants::TWO_POW_226, - 227 => constants::TWO_POW_227, - 228 => constants::TWO_POW_228, - 229 => constants::TWO_POW_229, - 230 => constants::TWO_POW_230, - 231 => constants::TWO_POW_231, - 232 => constants::TWO_POW_232, - 233 => constants::TWO_POW_233, - 234 => constants::TWO_POW_234, - 235 => constants::TWO_POW_235, - 236 => constants::TWO_POW_236, - 237 => constants::TWO_POW_237, - 238 => constants::TWO_POW_238, - 239 => constants::TWO_POW_239, - 240 => constants::TWO_POW_240, - 241 => constants::TWO_POW_241, - 242 => constants::TWO_POW_242, - 243 => constants::TWO_POW_243, - 244 => constants::TWO_POW_244, - 245 => constants::TWO_POW_245, - 246 => constants::TWO_POW_246, - 247 => constants::TWO_POW_247, - 248 => constants::TWO_POW_248, - 249 => constants::TWO_POW_249, - 250 => constants::TWO_POW_250, - 251 => constants::TWO_POW_251, - 252 => constants::TWO_POW_252, - _ => { - panic(array![errors::INVALID_INDEX,]); - 0 - }, - } - } -} - -#[cfg(test)] -mod tests { - // Core imports - - use core::debug::PrintTrait; - - // Local imports - - use super::{Bitmap}; - - #[test] - fn test_helpers_get_bit_at_0() { - let bitmap = 0; - let result = Bitmap::get_bit_at(bitmap, 0); - assert(!result, 'Bitmap: Invalid bit'); - } - - #[test] - fn test_helpers_get_bit_at_1() { - let bitmap = 255; - let result = Bitmap::get_bit_at(bitmap, 1); - assert(result, 'Bitmap: Invalid bit'); - } - - #[test] - fn test_helpers_get_bit_at_10() { - let bitmap = 3071; - let result = Bitmap::get_bit_at(bitmap, 10); - assert(!result, 'Bitmap: Invalid bit'); - } - - #[test] - fn test_helpers_set_bit_at_0() { - let bitmap = 0; - let result = Bitmap::set_bit_at(bitmap, 0, true); - assert(result == 1, 'Bitmap: Invalid bitmap'); - let result = Bitmap::set_bit_at(bitmap, 0, false); - assert(result == bitmap, 'Bitmap: Invalid bitmap'); - } - - #[test] - fn test_helpers_set_bit_at_1() { - let bitmap = 1; - let result = Bitmap::set_bit_at(bitmap, 1, true); - assert(result == 3, 'Bitmap: Invalid bitmap'); - let result = Bitmap::set_bit_at(bitmap, 1, false); - assert(result == bitmap, 'Bitmap: Invalid bitmap'); - } - - #[test] - fn test_helpers_set_bit_at_10() { - let bitmap = 3; - let result = Bitmap::set_bit_at(bitmap, 10, true); - assert(result == 1027, 'Bitmap: Invalid bitmap'); - let result = Bitmap::set_bit_at(bitmap, 10, false); - assert(result == bitmap, 'Bitmap: Invalid bitmap'); - } - - #[test] - #[should_panic(expected: ('Bitmap: invalid index',))] - fn test_helpers_set_bit_at_253() { - let bitmap = 0; - Bitmap::set_bit_at(bitmap, 253, true); - } -} diff --git a/examples/matchmaker/src/lib.cairo b/examples/matchmaker/src/lib.cairo deleted file mode 100644 index 5cd4710c..00000000 --- a/examples/matchmaker/src/lib.cairo +++ /dev/null @@ -1,26 +0,0 @@ -mod constants; -mod store; - -mod models { - mod league; - mod player; - mod registry; - mod slot; -} - -mod systems { - mod maker; -} - -mod helpers { - mod bitmap; -} - -#[cfg(test)] -mod tests { - mod setup; - mod test_create; - mod test_subscribe; - mod test_unsubscribe; - mod test_fight; -} diff --git a/examples/matchmaker/src/models/league.cairo b/examples/matchmaker/src/models/league.cairo deleted file mode 100644 index 61277647..00000000 --- a/examples/matchmaker/src/models/league.cairo +++ /dev/null @@ -1,190 +0,0 @@ -use core::option::OptionTrait; -// Starknet imports - -use starknet::ContractAddress; - -// Internal imports - -use matchmaker::constants::{LEAGUE_SIZE, LEAGUE_COUNT, LEAGUE_MIN_THRESHOLD}; -use matchmaker::models::player::{Player, PlayerTrait, PlayerAssert}; -use matchmaker::models::slot::{Slot, SlotTrait}; - -// Errors - -mod errors { - const LEAGUE_NOT_SUBSCRIBED: felt252 = 'League: player not subscribed'; -} - -#[dojo::model] -#[derive(Copy, Drop, Serde)] -struct League { - #[key] - registry_id: u32, - #[key] - id: u8, - size: u32, -} - -#[generate_trait] -impl LeagueImpl of LeagueTrait { - #[inline(always)] - fn new(registry_id: u32, league_id: u8) -> League { - League { registry_id, id: league_id, size: 0, } - } - - #[inline(always)] - fn compute_id(rating: u32) -> u8 { - if rating <= LEAGUE_MIN_THRESHOLD { - return 1; - } - let max_rating = LEAGUE_MIN_THRESHOLD + LEAGUE_SIZE.into() * LEAGUE_COUNT.into(); - if rating >= max_rating { - return LEAGUE_COUNT; - } - let id = 1 + (rating - LEAGUE_MIN_THRESHOLD) / LEAGUE_SIZE.into(); - if id > 251 { - 251 - } else if id < 1 { - 1 - } else { - id.try_into().unwrap() - } - } - - #[inline(always)] - fn subscribe(ref self: League, ref player: Player) -> Slot { - // [Check] Player can subscribe - PlayerAssert::assert_subscribable(player); - // [Effect] Update - let index = self.size; - self.size += 1; - player.league_id = self.id; - player.index = index; - // [Return] Corresponding slot - SlotTrait::new(player) - } - - #[inline(always)] - fn unsubscribe(ref self: League, ref player: Player) { - // [Check] Player belongs to the league - LeagueAssert::assert_subscribed(self, player); - // [Effect] Update - self.size -= 1; - player.league_id = 0; - player.index = 0; - } - - #[inline(always)] - fn search_player(self: League, seed: felt252) -> u32 { - let seed: u256 = seed.into(); - let index = seed % self.size.into(); - index.try_into().unwrap() - } -} - -#[generate_trait] -impl LeagueAssert of AssertTrait { - #[inline(always)] - fn assert_subscribed(self: League, player: Player) { - assert(player.league_id == self.id, errors::LEAGUE_NOT_SUBSCRIBED); - } -} - -#[cfg(test)] -mod tests { - // Core imports - - use core::debug::PrintTrait; - - // Local imports - - use super::{ - League, LeagueTrait, Player, PlayerTrait, ContractAddress, LEAGUE_SIZE, LEAGUE_COUNT, - LEAGUE_MIN_THRESHOLD - }; - - // Constants - - fn PLAYER() -> ContractAddress { - starknet::contract_address_const::<'PLAYER'>() - } - - const PLAYER_NAME: felt252 = 'NAME'; - const REGISTRY_ID: u32 = 1; - const LEAGUE_ID: u8 = 1; - - #[test] - fn test_new() { - let league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - assert_eq!(league.registry_id, REGISTRY_ID); - assert_eq!(league.id, LEAGUE_ID); - assert_eq!(league.size, 0); - } - - #[test] - fn test_compute_id() { - let rating = LEAGUE_MIN_THRESHOLD - 1; - let league_id = LeagueTrait::compute_id(rating); - assert_eq!(league_id, 1); - } - - #[test] - fn test_compute_id_overflow() { - let max_rating = LEAGUE_MIN_THRESHOLD + LEAGUE_SIZE.into() * LEAGUE_COUNT.into() + 1; - let league_id = LeagueTrait::compute_id(max_rating); - assert_eq!(league_id, LEAGUE_COUNT); - } - - #[test] - fn test_compute_id_underflow() { - let rating = 0; - let league_id = LeagueTrait::compute_id(rating); - assert_eq!(league_id, 1); - } - - #[test] - fn test_subscribe_once() { - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let slot = LeagueTrait::subscribe(ref league, ref player); - // [Assert] League - assert_eq!(league.size, 1); - // [Assert] Player - assert_eq!(player.league_id, LEAGUE_ID); - assert_eq!(player.index, 0); - // [Assert] Slot - assert_eq!(slot.player_id, player.id); - } - - #[test] - #[should_panic(expected: ('Player: not subscribable',))] - fn test_subscribe_twice() { - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - LeagueTrait::subscribe(ref league, ref player); - LeagueTrait::subscribe(ref league, ref player); - } - - #[test] - fn test_unsubscribe_once() { - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - LeagueTrait::subscribe(ref league, ref player); - LeagueTrait::unsubscribe(ref league, ref player); - // [Assert] League - assert_eq!(league.size, 0); - // [Assert] Player - assert_eq!(player.league_id, 0); - assert_eq!(player.index, 0); - } - - #[test] - #[should_panic(expected: ('League: player not subscribed',))] - fn test_unsubscribe_twice() { - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - LeagueTrait::subscribe(ref league, ref player); - LeagueTrait::unsubscribe(ref league, ref player); - LeagueTrait::unsubscribe(ref league, ref player); - } -} diff --git a/examples/matchmaker/src/models/player.cairo b/examples/matchmaker/src/models/player.cairo deleted file mode 100644 index e3b4e478..00000000 --- a/examples/matchmaker/src/models/player.cairo +++ /dev/null @@ -1,169 +0,0 @@ -// Core imports - -use core::zeroable::Zeroable; - -// Starknet imports - -use starknet::ContractAddress; - -// External imports - -use origami::rating::elo::EloTrait; - -// Internal imports - -use matchmaker::constants::{ZERO, DEFAULT_RATING, DEFAULT_K_FACTOR}; - -// Errors - -mod errors { - const PLAYER_DOES_NOT_EXIST: felt252 = 'Player: does not exist'; - const PLAYER_ALREADY_EXIST: felt252 = 'Player: already exist'; - const PLAYER_NOT_SUBSCRIBABLE: felt252 = 'Player: not subscribable'; - const PLAYER_NOT_SUBSCRIBED: felt252 = 'Player: not subscribed'; -} - -#[dojo::model] -#[derive(Copy, Drop, Serde)] -struct Player { - #[key] - registry_id: u32, - #[key] - id: ContractAddress, - name: felt252, - league_id: u8, - index: u32, - rating: u32, -} - -#[generate_trait] -impl PlayerImpl of PlayerTrait { - #[inline(always)] - fn new(registry_id: u32, id: ContractAddress, name: felt252) -> Player { - Player { registry_id, id, name, league_id: 0, index: 0, rating: DEFAULT_RATING, } - } - - #[inline(always)] - fn fight(ref self: Player, ref foe: Player, seed: felt252) { - let win: u8 = (seed.into() % 3_u256).try_into().unwrap(); - let score: u16 = match win { - 0 => 0, // Lose - 1 => 50, // Draw - 2 => 100, // Win - _ => 0, - }; - let (change, negative) = EloTrait::rating_change( - self.rating, foe.rating, score, DEFAULT_K_FACTOR - ); - if negative { - self.rating -= change; - foe.rating += change; - } else { - self.rating += change; - foe.rating -= change; - }; - } -} - -#[generate_trait] -impl PlayerAssert of AssertTrait { - #[inline(always)] - fn assert_does_exist(player: Player) { - assert(player.is_non_zero(), errors::PLAYER_DOES_NOT_EXIST); - } - - #[inline(always)] - fn assert_not_exist(player: Player) { - assert(player.is_zero(), errors::PLAYER_ALREADY_EXIST); - } - - #[inline(always)] - fn assert_subscribable(player: Player) { - assert(player.league_id == 0, errors::PLAYER_NOT_SUBSCRIBABLE); - } - - #[inline(always)] - fn assert_subscribed(player: Player) { - assert(player.league_id != 0, errors::PLAYER_NOT_SUBSCRIBED); - } -} - -impl PlayerZeroable of Zeroable { - #[inline(always)] - fn zero() -> Player { - Player { registry_id: 0, id: ZERO(), name: 0, league_id: 0, index: 0, rating: 0, } - } - - #[inline(always)] - fn is_zero(self: Player) -> bool { - self.league_id == 0 && self.index == 0 && self.rating == 0 - } - - #[inline(always)] - fn is_non_zero(self: Player) -> bool { - !self.is_zero() - } -} - -#[cfg(test)] -mod tests { - // Core imports - - use core::debug::PrintTrait; - - // Local imports - - use super::{Player, PlayerTrait, DEFAULT_RATING, ContractAddress, AssertTrait}; - - // Constants - - fn PLAYER() -> ContractAddress { - starknet::contract_address_const::<'PLAYER'>() - } - - const PLAYER_NAME: felt252 = 'NAME'; - const REGISTRY_ID: u32 = 1; - - #[test] - fn test_new() { - let player_id = PLAYER(); - let player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); - assert_eq!(player.registry_id, REGISTRY_ID); - assert_eq!(player.id, player_id); - assert_eq!(player.league_id, 0); - assert_eq!(player.index, 0); - assert_eq!(player.rating, DEFAULT_RATING); - } - - #[test] - fn test_subscribable() { - let player_id = PLAYER(); - let player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); - AssertTrait::assert_subscribable(player); - } - - #[test] - #[should_panic(expected: ('Player: not subscribable',))] - fn test_subscribable_revert_not_subscribable() { - let player_id = PLAYER(); - let mut player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); - player.league_id = 1; - AssertTrait::assert_subscribable(player); - } - - #[test] - fn test_subscribed() { - let player_id = PLAYER(); - let mut player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); - player.league_id = 1; - AssertTrait::assert_subscribed(player); - } - - #[test] - #[should_panic(expected: ('Player: not subscribed',))] - fn test_subscribed_revert_not_subscribed() { - let player_id = PLAYER(); - let player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); - AssertTrait::assert_subscribed(player); - } -} diff --git a/examples/matchmaker/src/models/registry.cairo b/examples/matchmaker/src/models/registry.cairo deleted file mode 100644 index 96d95b4e..00000000 --- a/examples/matchmaker/src/models/registry.cairo +++ /dev/null @@ -1,228 +0,0 @@ -// Starknet imports - -use starknet::ContractAddress; - -// Internal imports - -use matchmaker::constants::{LEAGUE_SIZE, DEFAULT_RATING}; -use matchmaker::store::{Store, StoreTrait}; -use matchmaker::models::league::{League, LeagueTrait}; -use matchmaker::models::player::{Player, PlayerTrait, PlayerAssert}; -use matchmaker::models::slot::{Slot, SlotTrait}; -use matchmaker::helpers::bitmap::Bitmap; - -// Errors - -mod errors { - const REGISTRY_INVALID_INDEX: felt252 = 'Registry: invalid bitmap index'; - const REGISTRY_IS_EMPTY: felt252 = 'Registry: is empty'; - const REGISTRY_LEAGUE_NOT_FOUND: felt252 = 'Registry: league not found'; -} - -#[dojo::model] -#[derive(Copy, Drop, Serde)] -struct Registry { - #[key] - id: u32, - leagues: felt252, -} - -#[generate_trait] -impl RegistryImpl of RegistryTrait { - #[inline(always)] - fn new(id: u32) -> Registry { - Registry { id, leagues: 0 } - } - - #[inline(always)] - fn subscribe(ref self: Registry, ref league: League, ref player: Player) -> Slot { - let slot = league.subscribe(ref player); - Private::update(ref self, league.id, league.size); - slot - } - - #[inline(always)] - fn unsubscribe(ref self: Registry, ref league: League, ref player: Player) { - league.unsubscribe(ref player); - Private::update(ref self, league.id, league.size); - } - - #[inline(always)] - fn search_league(ref self: Registry, ref league: League, ref player: Player) -> u8 { - // [Check] Player has subscribed - PlayerAssert::assert_subscribed(player); - // [Effect] Unsubcribe player from his league - self.unsubscribe(ref league, ref player); - // [Check] Registry is not empty - RegistryAssert::assert_not_empty(self); - // [Compute] Loop over the bitmap to find the nearest league with at least 1 player - match Bitmap::nearest_significant_bit(self.leagues.into(), league.id) { - Option::Some(bit) => bit, - Option::None => { - panic(array![errors::REGISTRY_LEAGUE_NOT_FOUND]); - 0 - }, - } - } -} - -#[generate_trait] -impl Private of PrivateTrait { - #[inline(always)] - fn update(ref registry: Registry, index: u8, count: u32,) { - let bit = Bitmap::get_bit_at(registry.leagues.into(), index.into()); - let new_bit = count != 0; - if bit != new_bit { - let leagues = Bitmap::set_bit_at(registry.leagues.into(), index.into(), new_bit); - registry.leagues = leagues.try_into().expect(errors::REGISTRY_INVALID_INDEX); - } - } -} - -#[generate_trait] -impl RegistryAssert of AssertTrait { - #[inline(always)] - fn assert_not_empty(registry: Registry) { - // [Check] Registry is not empty - assert(registry.leagues.into() > 0_u256, errors::REGISTRY_IS_EMPTY); - } -} - -#[cfg(test)] -mod tests { - // Core imports - - use core::debug::PrintTrait; - - // Local imports - - use super::{ - Registry, RegistryTrait, PrivateTrait, League, LeagueTrait, Slot, SlotTrait, Player, - PlayerTrait, ContractAddress - }; - - // Constants - - fn PLAYER() -> ContractAddress { - starknet::contract_address_const::<'PLAYER'>() - } - - fn TARGET() -> ContractAddress { - starknet::contract_address_const::<'TARGET'>() - } - - const PLAYER_NAME: felt252 = 'NAME'; - const REGISTRY_ID: u32 = 1; - const LEAGUE_ID: u8 = 1; - const CLOSEST_LEAGUE_ID: u8 = 2; - const TARGET_LEAGUE_ID: u8 = 100; - const FAREST_LEAGUE_ID: u8 = 251; - const INDEX: u8 = 3; - - #[test] - fn test_new() { - let registry = RegistryTrait::new(REGISTRY_ID); - assert_eq!(registry.id, REGISTRY_ID); - assert_eq!(registry.leagues, 0); - } - - #[test] - fn test_subscribe() { - let mut registry = RegistryTrait::new(REGISTRY_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - registry.subscribe(ref league, ref player); - // [Assert] Registry - assert(registry.leagues.into() > 0_u256, 'Registry: wrong leagues value'); - } - - #[test] - fn test_unsubscribe() { - let mut registry = RegistryTrait::new(REGISTRY_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - registry.subscribe(ref league, ref player); - registry.unsubscribe(ref league, ref player); - // [Assert] Registry - assert_eq!(registry.leagues, 0); - } - - #[test] - fn test_search_league_same() { - let mut registry = RegistryTrait::new(REGISTRY_ID); - let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - registry.subscribe(ref league, ref player); - let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET(), PLAYER_NAME); - registry.subscribe(ref league, ref foe); - let league_id = registry.search_league(ref league, ref player); - // [Assert] Registry - assert(league_id == LEAGUE_ID, 'Registry: wrong search league'); - } - - #[test] - fn test_search_league_close() { - let mut registry = RegistryTrait::new(REGISTRY_ID); - let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - registry.subscribe(ref league, ref player); - let mut foe_league = LeagueTrait::new(REGISTRY_ID, CLOSEST_LEAGUE_ID); - let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET(), PLAYER_NAME); - registry.subscribe(ref foe_league, ref foe); - let league_id = registry.search_league(ref league, ref player); - // [Assert] Registry - assert(league_id == CLOSEST_LEAGUE_ID, 'Registry: wrong search league'); - } - - #[test] - fn test_search_league_target() { - let mut registry = RegistryTrait::new(REGISTRY_ID); - let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - registry.subscribe(ref league, ref player); - let mut foe_league = LeagueTrait::new(REGISTRY_ID, TARGET_LEAGUE_ID); - let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET(), PLAYER_NAME); - registry.subscribe(ref foe_league, ref foe); - let league_id = registry.search_league(ref league, ref player); - // [Assert] Registry - assert(league_id == TARGET_LEAGUE_ID, 'Registry: wrong search league'); - } - - #[test] - fn test_search_league_far_down_top() { - let mut registry = RegistryTrait::new(REGISTRY_ID); - let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - registry.subscribe(ref league, ref player); - let mut foe_league = LeagueTrait::new(REGISTRY_ID, FAREST_LEAGUE_ID); - let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET(), PLAYER_NAME); - registry.subscribe(ref foe_league, ref foe); - let league_id = registry.search_league(ref league, ref player); - // [Assert] Registry - assert(league_id == FAREST_LEAGUE_ID, 'Registry: wrong search league'); - } - - #[test] - fn test_search_league_far_top_down() { - let mut registry = RegistryTrait::new(REGISTRY_ID); - let mut league = LeagueTrait::new(REGISTRY_ID, FAREST_LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - registry.subscribe(ref league, ref player); - let mut foe_league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET(), PLAYER_NAME); - registry.subscribe(ref foe_league, ref foe); - let league_id = registry.search_league(ref league, ref player); - // [Assert] Registry - assert(league_id == LEAGUE_ID, 'Registry: wrong search league'); - } - - #[test] - #[should_panic(expected: ('Registry: is empty',))] - fn test_search_league_revert_empty() { - let mut registry = RegistryTrait::new(REGISTRY_ID); - let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); - registry.subscribe(ref league, ref player); - registry.search_league(ref league, ref player); - } -} diff --git a/examples/matchmaker/src/models/slot.cairo b/examples/matchmaker/src/models/slot.cairo deleted file mode 100644 index ac5018a1..00000000 --- a/examples/matchmaker/src/models/slot.cairo +++ /dev/null @@ -1,73 +0,0 @@ -// Starknet imports - -use starknet::ContractAddress; - -// Internal imports - -use matchmaker::constants::ZERO; -use matchmaker::models::player::{Player, PlayerTrait}; - -#[dojo::model] -#[derive(Copy, Drop, Serde)] -struct Slot { - #[key] - registry_id: u32, - #[key] - league_id: u8, - #[key] - index: u32, - player_id: ContractAddress, -} - -#[generate_trait] -impl SlotImpl of SlotTrait { - #[inline(always)] - fn new(player: Player) -> Slot { - Slot { - registry_id: player.registry_id, - league_id: player.league_id, - index: player.index, - player_id: player.id, - } - } - - #[inline(always)] - fn nullify(ref self: Slot) { - self.player_id = ZERO(); - } -} - -#[cfg(test)] -mod tests { - // Core imports - - use core::debug::PrintTrait; - - // Local imports - - use super::{Slot, SlotTrait, Player, PlayerTrait, ContractAddress}; - - // Constants - - fn PLAYER() -> ContractAddress { - starknet::contract_address_const::<'PLAYER'>() - } - - const PLAYER_NAME: felt252 = 'NAME'; - const REGISTRY_ID: u32 = 1; - const LEAGUE_ID: u8 = 2; - const INDEX: u32 = 3; - - #[test] - fn test_new() { - let player_id = PLAYER(); - let mut player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); - player.league_id = LEAGUE_ID; - player.index = INDEX; - let slot = SlotTrait::new(player); - assert_eq!(slot.registry_id, REGISTRY_ID); - assert_eq!(slot.league_id, LEAGUE_ID); - assert_eq!(slot.index, INDEX); - assert_eq!(slot.player_id, player_id); - } -} diff --git a/examples/matchmaker/src/store.cairo b/examples/matchmaker/src/store.cairo deleted file mode 100644 index 1002bb06..00000000 --- a/examples/matchmaker/src/store.cairo +++ /dev/null @@ -1,96 +0,0 @@ -//! Store struct and component management methods. - -// Core imports - -use core::debug::PrintTrait; - -// Straknet imports - -use starknet::ContractAddress; - -// Dojo imports - -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - -// Models imports - -use matchmaker::models::league::{League, LeagueTrait}; -use matchmaker::models::player::Player; -use matchmaker::models::registry::Registry; -use matchmaker::models::slot::{Slot, SlotTrait}; - - -/// Store struct. -#[derive(Copy, Drop)] -struct Store { - world: IWorldDispatcher, -} - -/// Implementation of the `StoreTrait` trait for the `Store` struct. -#[generate_trait] -impl StoreImpl of StoreTrait { - #[inline(always)] - fn new(world: IWorldDispatcher) -> Store { - Store { world: world } - } - - #[inline(always)] - fn registry(self: Store, registry_id: u32,) -> Registry { - get!(self.world, registry_id, (Registry)) - } - - #[inline(always)] - fn league(self: Store, registry_id: u32, league_id: u8) -> League { - get!(self.world, (registry_id, league_id), (League)) - } - - #[inline(always)] - fn slot(self: Store, registry_id: u32, league_id: u8, index: u32) -> Slot { - get!(self.world, (registry_id, league_id, index), (Slot)) - } - - #[inline(always)] - fn player(self: Store, registry_id: u32, player_id: ContractAddress) -> Player { - get!(self.world, (registry_id, player_id), (Player)) - } - - #[inline(always)] - fn set_registry(self: Store, registry: Registry) { - set!(self.world, (registry)) - } - - #[inline(always)] - fn set_league(self: Store, league: League) { - set!(self.world, (league)) - } - - #[inline(always)] - fn set_slot(self: Store, slot: Slot) { - set!(self.world, (slot)) - } - - #[inline(always)] - fn set_player(self: Store, player: Player) { - set!(self.world, (player)) - } - - #[inline(always)] - fn remove_player_slot(self: Store, player: Player) { - // [Effect] Replace the slot with the last slot if needed - let league = self.league(player.registry_id, player.league_id); - let mut player_slot = self.slot(player.registry_id, player.league_id, player.index); - let mut last_slot = self.slot(player.registry_id, player.league_id, league.size - 1); - if last_slot.index != player_slot.index { - let mut last_player = self.player(player.registry_id, last_slot.player_id); - let last_slot_index = last_slot.index; - last_slot.index = player_slot.index; - last_player.index = player_slot.index; - player_slot.index = last_slot_index; - self.set_player(last_player); - self.set_slot(last_slot); - } - // [Effect] Remove the last slot - player_slot.nullify(); - self.set_slot(player_slot); - } -} diff --git a/examples/matchmaker/src/systems/maker.cairo b/examples/matchmaker/src/systems/maker.cairo deleted file mode 100644 index ad9f1047..00000000 --- a/examples/matchmaker/src/systems/maker.cairo +++ /dev/null @@ -1,205 +0,0 @@ -// Starknet imports - -use starknet::ContractAddress; - -// Dojo imports - -use dojo::world::IWorldDispatcher; - -// Interface - -#[starknet::interface] -trait IMaker { - fn create(self: @TContractState, world: IWorldDispatcher, name: felt252); - fn subscribe(self: @TContractState, world: IWorldDispatcher); - fn unsubscribe(self: @TContractState, world: IWorldDispatcher); - fn fight(self: @TContractState, world: IWorldDispatcher); -} - -// Contract - -#[starknet::contract] -mod maker { - // Core imports - - use core::array::ArrayTrait; - use core::debug::PrintTrait; - - // Starknet imports - - use starknet::ContractAddress; - use starknet::info::{get_caller_address, get_tx_info}; - - // Dojo imports - - use dojo::world; - use dojo::world::IWorldDispatcher; - use dojo::world::IWorldDispatcherTrait; - use dojo::world::IWorldProvider; - use dojo::world::IDojoResourceProvider; - - // Internal imports - - use matchmaker::constants::WORLD; - use matchmaker::store::{Store, StoreTrait}; - use matchmaker::models::player::{Player, PlayerTrait, PlayerAssert}; - use matchmaker::models::league::{League, LeagueTrait, LeagueAssert}; - use matchmaker::models::registry::{Registry, RegistryTrait, RegistryAssert}; - use matchmaker::models::slot::{Slot, SlotTrait}; - - // Local imports - - use super::IMaker; - - // Errors - - mod errors { - const CHARACTER_DUPLICATE: felt252 = 'Battle: character duplicate'; - } - - // Storage - - #[storage] - struct Storage {} - - // Implementations - - #[abi(embed_v0)] - impl DojoResourceProviderImpl of IDojoResourceProvider { - fn dojo_resource(self: @ContractState) -> felt252 { - 'account' - } - } - - #[abi(embed_v0)] - impl WorldProviderImpl of IWorldProvider { - fn world(self: @ContractState) -> IWorldDispatcher { - IWorldDispatcher { contract_address: WORLD() } - } - } - - #[abi(embed_v0)] - impl MakerImpl of IMaker { - fn create(self: @ContractState, world: IWorldDispatcher, name: felt252) { - // [Setup] Datastore - let mut store: Store = StoreTrait::new(world); - - // [Check] Player does not exist - let caller = get_caller_address(); - let player = store.player(0, caller); - PlayerAssert::assert_not_exist(player); - - // [Effect] Create one - let player = PlayerTrait::new(0, caller, name); - store.set_player(player); - } - - fn subscribe(self: @ContractState, world: IWorldDispatcher) { - // [Setup] Datastore - let mut store: Store = StoreTrait::new(world); - - // [Check] Player exists - let caller = get_caller_address(); - let mut player = store.player(0, caller); - PlayerAssert::assert_does_exist(player); - - // [Effect] Subscribe to Registry - let league_id = LeagueTrait::compute_id(player.rating); - let mut league = store.league(0, league_id); - let mut registry = store.registry(0); - let slot = registry.subscribe(ref league, ref player); - - // [Effect] Update Slot - store.set_slot(slot); - - // [Effect] Update Player - store.set_player(player); - - // [Effect] Update League - store.set_league(league); - - // [Effect] Update Registry - store.set_registry(registry); - } - - fn unsubscribe(self: @ContractState, world: IWorldDispatcher) { - // [Setup] Datastore - let mut store: Store = StoreTrait::new(world); - - // [Check] Player exists - let caller = get_caller_address(); - let mut player = store.player(0, caller); - PlayerAssert::assert_does_exist(player); - - // [Effect] Remove slot - store.remove_player_slot(player); - - // [Effect] Unsubscribe to Registry - let mut league = store.league(player.registry_id, player.league_id); - let mut registry = store.registry(player.registry_id); - registry.unsubscribe(ref league, ref player); - - // [Effect] Update Player - store.set_player(player); - - // [Effect] Update League - store.set_league(league); - - // [Effect] Update Registry - store.set_registry(registry); - } - - fn fight(self: @ContractState, world: IWorldDispatcher) { - // [Setup] Datastore - let mut store: Store = StoreTrait::new(world); - - // [Check] Player exists - let caller = get_caller_address(); - let mut player = store.player(0, caller); - PlayerAssert::assert_does_exist(player); - - // [Effect] Remove slot - store.remove_player_slot(player); - - // [Effect] Search opponent which unsubscribe, then update league - let seed = get_tx_info().unbox().transaction_hash; - let mut registry = store.registry(0); - let mut player_league = store.league(0, player.league_id); - let foe_league_id = registry.search_league(ref player_league, ref player); - store.set_league(player_league); - - // [Compute] Foe - let mut foe_league = store.league(0, foe_league_id); - let foe_slot_id = foe_league.search_player(seed); - let foe_slot = store.slot(0, foe_league_id, foe_slot_id); - let mut foe = store.player(0, foe_slot.player_id); - - // [Effect] Remove foe slot, unsubscribe and update league - store.remove_player_slot(foe); - registry.unsubscribe(ref foe_league, ref foe); - store.set_league(foe_league); - - // [Effect] Fight and update players - player.fight(ref foe, seed); - - // [Effect] Update player, league and slot - let league_id = LeagueTrait::compute_id(player.rating); - let mut league = store.league(0, league_id); - let slot = registry.subscribe(ref league, ref player); - store.set_league(league); - store.set_slot(slot); - store.set_player(player); - - // [Effect] Update Foe, league and slot - let league_id = LeagueTrait::compute_id(foe.rating); - let mut league = store.league(0, league_id); - let slot = registry.subscribe(ref league, ref foe); - store.set_league(league); - store.set_slot(slot); - store.set_player(foe); - - // [Effect] Update Registry - store.set_registry(registry); - } - } -} diff --git a/examples/matchmaker/src/tests/setup.cairo b/examples/matchmaker/src/tests/setup.cairo deleted file mode 100644 index 9fc86243..00000000 --- a/examples/matchmaker/src/tests/setup.cairo +++ /dev/null @@ -1,82 +0,0 @@ -mod setup { - // Core imports - - use core::debug::PrintTrait; - - // Starknet imports - - use starknet::ContractAddress; - use starknet::testing::{set_contract_address}; - - // Dojo imports - - use dojo::world::{IWorldDispatcherTrait, IWorldDispatcher}; - use dojo::test_utils::{spawn_test_world, deploy_contract}; - - // Internal imports - - use matchmaker::models::player::Player; - use matchmaker::models::league::League; - use matchmaker::models::registry::Registry; - use matchmaker::models::slot::Slot; - use matchmaker::systems::maker::{maker, IMakerDispatcher, IMakerDispatcherTrait}; - - // Constants - - fn PLAYER() -> ContractAddress { - starknet::contract_address_const::<'PLAYER'>() - } - - fn SOMEONE() -> ContractAddress { - starknet::contract_address_const::<'SOMEONE'>() - } - - const PLAYER_NAME: felt252 = 'PLAYER'; - const SOMEONE_NAME: felt252 = 'SOMEONE'; - const REGISTRY_ID: u32 = 0; - - #[derive(Drop)] - struct Systems { - maker: IMakerDispatcher, - } - - #[derive(Drop)] - struct Context { - registry_id: u32, - player_id: ContractAddress, - someone_id: ContractAddress, - player_name: felt252, - someone_name: felt252, - } - - #[inline(always)] - fn spawn() -> (IWorldDispatcher, Systems, Context) { - // [Setup] World - let mut models = core::array::ArrayTrait::new(); - models.append(matchmaker::models::player::player::TEST_CLASS_HASH); - models.append(matchmaker::models::league::league::TEST_CLASS_HASH); - models.append(matchmaker::models::registry::registry::TEST_CLASS_HASH); - models.append(matchmaker::models::slot::slot::TEST_CLASS_HASH); - let world = spawn_test_world(models); - - // [Setup] Systems - let maker_address = deploy_contract(maker::TEST_CLASS_HASH, array![].span()); - let systems = Systems { maker: IMakerDispatcher { contract_address: maker_address }, }; - - // [Setup] Context - set_contract_address(SOMEONE()); - systems.maker.create(world, SOMEONE_NAME); - systems.maker.subscribe(world); - set_contract_address(PLAYER()); - let context = Context { - registry_id: REGISTRY_ID, - player_id: PLAYER(), - someone_id: SOMEONE(), - player_name: PLAYER_NAME, - someone_name: SOMEONE_NAME, - }; - - // [Return] - (world, systems, context) - } -} diff --git a/examples/matchmaker/src/tests/test_create.cairo b/examples/matchmaker/src/tests/test_create.cairo deleted file mode 100644 index f77607a7..00000000 --- a/examples/matchmaker/src/tests/test_create.cairo +++ /dev/null @@ -1,36 +0,0 @@ -// Core imports - -use core::debug::PrintTrait; - -// Starknet imports - -use starknet::testing::set_contract_address; - -// Dojo imports - -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - -// Internal imports - -use matchmaker::store::{Store, StoreTrait}; -use matchmaker::models::player::{Player, PlayerTrait, PlayerAssert}; -use matchmaker::models::registry::{Registry, RegistryTrait, RegistryAssert}; -use matchmaker::models::league::{League, LeagueTrait, LeagueAssert}; -use matchmaker::models::slot::{Slot, SlotTrait}; -use matchmaker::systems::maker::IMakerDispatcherTrait; -use matchmaker::tests::setup::{setup, setup::Systems}; - -#[test] -fn test_maker_create() { - // [Setup] - let (world, systems, context) = setup::spawn(); - let store = StoreTrait::new(world); - - // [Create] - systems.maker.create(world, context.player_name); - - // [Assert] Player - let player = store.player(context.registry_id, context.player_id); - assert(player.id == context.player_id, 'Create: wrong player id'); - assert(player.league_id == 0, 'Create: wrong league id'); -} diff --git a/examples/matchmaker/src/tests/test_fight.cairo b/examples/matchmaker/src/tests/test_fight.cairo deleted file mode 100644 index ca682dbf..00000000 --- a/examples/matchmaker/src/tests/test_fight.cairo +++ /dev/null @@ -1,138 +0,0 @@ -// Core imports - -use core::debug::PrintTrait; - -// Starknet imports - -use starknet::testing::{set_contract_address, set_transaction_hash}; - -// Dojo imports - -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - -// Internal imports - -use matchmaker::constants::DEFAULT_RATING; -use matchmaker::store::{Store, StoreTrait}; -use matchmaker::models::player::{Player, PlayerTrait, PlayerAssert}; -use matchmaker::models::registry::{Registry, RegistryTrait, RegistryAssert}; -use matchmaker::models::league::{League, LeagueTrait, LeagueAssert}; -use matchmaker::models::slot::{Slot, SlotTrait}; -use matchmaker::systems::maker::IMakerDispatcherTrait; -use matchmaker::tests::setup::{setup, setup::Systems}; - -#[test] -fn test_maker_fight_lose() { - // [Setup] - let (world, systems, context) = setup::spawn(); - let store = StoreTrait::new(world); - - // [Create] - systems.maker.create(world, context.player_name); - - // [Subscribe] - systems.maker.subscribe(world); - - // [Fight] - set_transaction_hash(0); - systems.maker.fight(world); - - // [Assert] Player - let player = store.player(context.registry_id, context.player_id); - assert(player.rating != DEFAULT_RATING, 'Fight: wrong player rating'); - - // [Assert] Someone - let someone = store.player(context.registry_id, context.someone_id); - assert(someone.rating != DEFAULT_RATING, 'Fight: wrong player rating'); - - // [Assert] Global rating - let total = 2 * DEFAULT_RATING; - assert(player.rating + someone.rating == total, 'Fight: wrong global rating'); -} - -#[test] -fn test_maker_fight_draw() { - // [Setup] - let (world, systems, context) = setup::spawn(); - let store = StoreTrait::new(world); - - // [Create] - systems.maker.create(world, context.player_name); - - // [Subscribe] - systems.maker.subscribe(world); - - // [Fight] - set_transaction_hash(1); - systems.maker.fight(world); - - // [Assert] Player - let player = store.player(context.registry_id, context.player_id); - assert(player.rating == DEFAULT_RATING, 'Fight: wrong player rating'); - - // [Assert] Someone - let someone = store.player(context.registry_id, context.someone_id); - assert(someone.rating == DEFAULT_RATING, 'Fight: wrong player rating'); - - // [Assert] Global rating - let total = 2 * DEFAULT_RATING; - assert(player.rating + someone.rating == total, 'Fight: wrong global rating'); -} - -#[test] -fn test_maker_fight_win() { - // [Setup] - let (world, systems, context) = setup::spawn(); - let store = StoreTrait::new(world); - - // [Create] - systems.maker.create(world, context.player_name); - - // [Subscribe] - systems.maker.subscribe(world); - - // [Fight] - set_transaction_hash(2); - systems.maker.fight(world); - - // [Assert] Player - let player = store.player(context.registry_id, context.player_id); - assert(player.rating != DEFAULT_RATING, 'Fight: wrong player rating'); - - // [Assert] Someone - let someone = store.player(context.registry_id, context.someone_id); - assert(someone.rating != DEFAULT_RATING, 'Fight: wrong player rating'); - - // [Assert] Global rating - let total = 2 * DEFAULT_RATING; - assert(player.rating + someone.rating == total, 'Fight: wrong global rating'); -} - -#[test] -fn test_maker_fight_several_times() { - // [Setup] - let (world, systems, context) = setup::spawn(); - let store = StoreTrait::new(world); - - // [Create] - systems.maker.create(world, context.player_name); - - // [Subscribe] - systems.maker.subscribe(world); - - // [Fight] - let mut iter = 2; - loop { - if iter == 0 { - break; - } - systems.maker.fight(world); - iter -= 1; - }; - - // [Assert] Global rating - let total = 2 * DEFAULT_RATING; - let player = store.player(context.registry_id, context.player_id); - let someone = store.player(context.registry_id, context.someone_id); - assert(player.rating + someone.rating == total, 'Fight: wrong global rating'); -} diff --git a/examples/matchmaker/src/tests/test_subscribe.cairo b/examples/matchmaker/src/tests/test_subscribe.cairo deleted file mode 100644 index b208ba37..00000000 --- a/examples/matchmaker/src/tests/test_subscribe.cairo +++ /dev/null @@ -1,38 +0,0 @@ -// Core imports - -use core::debug::PrintTrait; - -// Starknet imports - -use starknet::testing::set_contract_address; - -// Dojo imports - -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - -// Internal imports - -use matchmaker::store::{Store, StoreTrait}; -use matchmaker::models::player::{Player, PlayerTrait, PlayerAssert}; -use matchmaker::models::registry::{Registry, RegistryTrait, RegistryAssert}; -use matchmaker::models::league::{League, LeagueTrait, LeagueAssert}; -use matchmaker::models::slot::{Slot, SlotTrait}; -use matchmaker::systems::maker::IMakerDispatcherTrait; -use matchmaker::tests::setup::{setup, setup::Systems}; - -#[test] -fn test_maker_subscribe() { - // [Setup] - let (world, systems, context) = setup::spawn(); - let store = StoreTrait::new(world); - - // [Create] - systems.maker.create(world, context.player_name); - - // [Subscribe] - systems.maker.subscribe(world); - - // [Assert] Player - let player = store.player(context.registry_id, context.player_id); - assert(player.league_id != 0, 'Sub: wrong league id'); -} diff --git a/examples/matchmaker/src/tests/test_unsubscribe.cairo b/examples/matchmaker/src/tests/test_unsubscribe.cairo deleted file mode 100644 index 8aa89cbc..00000000 --- a/examples/matchmaker/src/tests/test_unsubscribe.cairo +++ /dev/null @@ -1,41 +0,0 @@ -// Core imports - -use core::debug::PrintTrait; - -// Starknet imports - -use starknet::testing::set_contract_address; - -// Dojo imports - -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - -// Internal imports - -use matchmaker::store::{Store, StoreTrait}; -use matchmaker::models::player::{Player, PlayerTrait, PlayerAssert}; -use matchmaker::models::registry::{Registry, RegistryTrait, RegistryAssert}; -use matchmaker::models::league::{League, LeagueTrait, LeagueAssert}; -use matchmaker::models::slot::{Slot, SlotTrait}; -use matchmaker::systems::maker::IMakerDispatcherTrait; -use matchmaker::tests::setup::{setup, setup::Systems}; - -#[test] -fn test_maker_unsubscribe() { - // [Setup] - let (world, systems, context) = setup::spawn(); - let store = StoreTrait::new(world); - - // [Create] - systems.maker.create(world, context.player_name); - - // [Subscribe] - systems.maker.subscribe(world); - - // [Subscribe] - systems.maker.unsubscribe(world); - - // [Assert] Player - let player = store.player(context.registry_id, context.player_id); - assert(player.league_id == 0, 'Unsub: wrong league id'); -} diff --git a/examples/projectile/Scarb.toml b/examples/projectile/Scarb.toml deleted file mode 100644 index 295e39c4..00000000 --- a/examples/projectile/Scarb.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "projectile" -version = "0.0.0" -description = "Example of algebria crate usage." -homepage = "https://github.com/dojoengine/origami/tree/examples/projectile" - -[dependencies] -cubit.workspace = true -dojo.workspace = true -origami.workspace = true \ No newline at end of file diff --git a/examples/projectile/src/lib.cairo b/examples/projectile/src/lib.cairo deleted file mode 100644 index 9d1ead25..00000000 --- a/examples/projectile/src/lib.cairo +++ /dev/null @@ -1,252 +0,0 @@ -// External imports - -use cubit::f128::types::fixed::{Fixed, FixedTrait, ONE_u128}; -use cubit::f128::math::trig; - -// Internal imports - -use origami::algebra::vec2::{Vec2, Vec2Trait}; - -fn main() -> (usize, Array::, Array::) { - // to be inputs for #[view] function - // v_0_mag_felt: felt252, theta_0_deg_felt: felt252, x_0_felt: felt252, y_0_felt: felt252 - - // - // Projectile parameters - // - /// Inputs: to be contract inputs for view function `main` - /// Launch velocity magnitude, 0 <= v_0_felt <= 100 - let v_0_mag_felt = 100; - /// Launch angle in degrees, -180 <= theta_0_deg_felt <= 180 - let theta_0_deg_felt = 65; - /// Initial horizontal position, x_min <= x_0_felt <= x_max - let x_0_felt = 0; - /// Initial vertical position, y_min <= y_0_felt <= y_max - let y_0_felt = 0; - /// Convert inputs to signed fixed-point - let v_0_mag = FixedTrait::from_unscaled_felt(v_0_mag_felt); - let theta_0_deg = FixedTrait::from_unscaled_felt(theta_0_deg_felt); - let x_0 = FixedTrait::from_unscaled_felt(x_0_felt); - let y_0 = FixedTrait::from_unscaled_felt(y_0_felt); - - /// Convert theta_0_deg to radians - let theta_0 = deg_to_rad(theta_0_deg); - - // Gravitational acceleration magnitude - let g = FixedTrait::new(98 * ONE_u128 / 10, false); // 9.8 - // Plot parameters - let x_max = FixedTrait::from_unscaled_felt(1000); - let x_min = FixedTrait::from_unscaled_felt(-1000); - let y_max = FixedTrait::from_unscaled_felt(500); - let y_min = FixedTrait::from_unscaled_felt(-500); - // Check that inputs are within required ranges - assert(v_0_mag.mag <= 100 * ONE_u128, 'need v_0_mag_felt <= 100'); - assert(v_0_mag.mag > 0 * ONE_u128, 'need v_0_mag_felt > 0'); - assert(v_0_mag.sign == false, 'need v_0_mag_felt > 0'); - // `theta_0_deg.mag` not exact after conversion, so use 180.0000001 - assert(theta_0_deg.mag <= 180000001 * ONE_u128 / 1000000, '-180 <= theta_0_deg_felt <= 180'); - assert(x_0 <= x_max, 'need x_0 <= x_max'); - assert(x_0 >= x_min, 'need x_0 >= x_min'); - assert(y_0 <= y_max, 'need y_0 <= y_max'); - assert(y_0 >= y_min, 'need y_0 >= y_min'); - // Initial position vector - let r_0 = Vec2Trait::::new(x_0, y_0); - // Initial velocity vector - let v_0 = vec2_from_mag_theta(v_0_mag, theta_0); - - // Time interval between plotted points - let delta_t = FixedTrait::from_unscaled_felt(2); // arbitrary value 2 chosen - - // Tuples to pass to functions - let plot_params = (x_max, x_min, y_max, y_min); - let motion_params = (r_0, v_0, g, delta_t); - let (mut x_s, mut y_s) = fill_position_s(plot_params, motion_params); - (x_s.len(), x_s, y_s) -} - -fn deg_to_rad(theta_deg: Fixed) -> Fixed { - let pi = FixedTrait::new(trig::PI_u128, false); - let one_eighty = FixedTrait::new(180 * ONE_u128, false); - theta_deg * pi / one_eighty -} - -// Creates Fixed type Vec2 from magnitude, theta in radians -fn vec2_from_mag_theta(mag: Fixed, theta: Fixed) -> Vec2 { - let x_comp = mag * trig::cos(theta); // trig::cos works only for Fixed type - let y_comp = mag * trig::sin(theta); // trig::sin works only for Fixed type - Vec2:: { x: x_comp, y: y_comp } -} - -fn fill_position_s( - plot_params: (Fixed, Fixed, Fixed, Fixed), - motion_params: (Vec2, Vec2, Fixed, Fixed) -) -> (Array::, Array::) { - let (x_max, x_min, _y_max, y_min) = plot_params; - let (r_0, v_0, g, delta_t) = motion_params; - let mut x_s = ArrayTrait::::new(); - let mut y_s = ArrayTrait::::new(); - - let one = FixedTrait::new(ONE_u128, false); - let mut n = FixedTrait::new(0, false); - - loop { - // match withdraw_gas() { - // Option::Some(_) => {}, - // Option::None(_) => { - // let mut data = ArrayTrait::new(); - // data.append('Out of gas'); - // panic(data); - // }, - // } - let t = n * delta_t; - // 'n'.print(); - // n.mag.print(); - let x = calc_x(r_0.x, v_0.x, t); - // 'x'.print(); - // x.mag.print(); - // x.sign.print(); - let y = calc_y(r_0.y, v_0.y, g, t); - // 'y'.print(); - // y.mag.print(); - // y.sign.print(); - if x >= x_max || x <= x_min || y <= y_min { - break (); - } - - x_s.append(x); - y_s.append(y); - - n += one; - }; - - (x_s, y_s) -} - -fn calc_x(x_0: Fixed, v_0x: Fixed, t: Fixed) -> Fixed { - x_0 + v_0x * t -} - -fn calc_y(y_0: Fixed, v_0y: Fixed, g: Fixed, t: Fixed) -> Fixed { - let half = FixedTrait::new(5 * ONE_u128 / 10, false); - y_0 + v_0y * t - half * g * t * t -} - -#[cfg(test)] -mod tests { - // External imports - - use cubit::f128::test::helpers::assert_precise; - - // Local imports - - use super::{deg_to_rad, fill_position_s, vec2_from_mag_theta, calc_x, calc_y}; - use super::{Vec2Trait, Fixed, FixedTrait, ONE_u128}; - #[test] - fn test_deg_to_rad() { - let sixty = FixedTrait::new(60 * ONE_u128, false); - let theta = deg_to_rad(sixty); - assert_precise(theta, 19317385221538994246, 'invalid PI/3', Option::None(())); - assert(theta.sign == false, 'invalid sign'); - - let minus_120 = FixedTrait::new(120 * ONE_u128, true); - let theta = deg_to_rad(minus_120); - assert_precise(theta, -38634770443077988493, 'invalid -2*PI/3', Option::None(())); - assert(theta.sign == true, 'invalid sign'); - } - - #[test] - fn test_vec2_from_mag_theta() { - let mag = FixedTrait::new(100 * ONE_u128, false); - let sixty = FixedTrait::new(60 * ONE_u128, false); - let theta = deg_to_rad(sixty); - let vec2 = vec2_from_mag_theta(mag, theta); - assert_precise(vec2.x, 922337203685477580800, 'invalid vec2.x mag', Option::None(())); // 50 - assert(vec2.x.sign == false, 'invalid vec2.x.sign'); - assert_precise( - vec2.y, 1597534898494251510150, 'invalid vec2.y mag', Option::None(()) - ); // 86.6 - assert(vec2.y.sign == false, 'invalid vec2.y.sig'); - - let minus_120 = FixedTrait::new(120 * ONE_u128, true); - let theta = deg_to_rad(minus_120); - let vec2 = vec2_from_mag_theta(mag, theta); - assert_precise( - vec2.x, -922337203685477580800, 'invalid vec2.x mag', Option::None(()) - ); // -50 - assert(vec2.x.sign == true, 'invalid vec2.x.sign'); - assert_precise( - vec2.y, -1597534898494251510150, 'invalid vec2.y mag', Option::None(()) - ); // -86.6 - assert(vec2.y.sign == true, 'invalid vec2.y.sig'); - } - - #[test] - fn test_fill_position_s() { - let v_0_mag = FixedTrait::from_unscaled_felt(100); - let theta_0_deg = FixedTrait::from_unscaled_felt(65); - let theta_0 = deg_to_rad(theta_0_deg); - let x_0 = FixedTrait::from_unscaled_felt(0); - let y_0 = FixedTrait::from_unscaled_felt(0); - - let x_max = FixedTrait::from_unscaled_felt(1000); - let x_min = FixedTrait::from_unscaled_felt(-1000); - let y_max = FixedTrait::from_unscaled_felt(500); - let y_min = FixedTrait::from_unscaled_felt(-500); - - let r_0 = Vec2Trait::::new(x_0, y_0); - let v_0 = vec2_from_mag_theta(v_0_mag, theta_0); - let g = FixedTrait::new(98 * ONE_u128 / 10, false); - let delta_t = FixedTrait::from_unscaled_felt(2); - - let plot_params = (x_max, x_min, y_max, y_min); - let motion_params = (r_0, v_0, g, delta_t); - - let mut position_s: (Array, Array) = fill_position_s( - plot_params, motion_params - ); - - let (x_s, y_s) = position_s; - let length = x_s.len(); - assert(length == 12, 'invalid length'); - - assert_precise( - *x_s[5], 7795930915206679528264, 'invalid x_s[5]', Option::None(()) - ); // 422.61826174069944 - assert(*x_s.at(5).sign == false, 'invalid sign'); - assert_precise( - *y_s[5], 7679523203357457794972, 'invalid y_s[5]', Option::None(()) - ); // 416.3077870366498 - assert(*y_s.at(5).sign == false, 'invalid sign'); - - assert_precise( - *x_s[10], 15591861830413359425462, 'invalid x_s[10]', Option::None(()) - ); // 845.2365234813989, custom precision 1e-6 - assert(*x_s.at(10).sign == false, 'invalid sign'); - assert_precise( - *y_s[10], -2718762785520446838411, 'invalid y_s[10]', Option::None(()) - ); // -147.3844259267005, custom precision 1e-6 - assert(*y_s.at(10).sign == true, 'invalid sign'); - } - - #[test] - fn test_calc_x() { - let x_0 = FixedTrait::new(100 * ONE_u128, false); - let v_0x = FixedTrait::new(50 * ONE_u128, false); - let t = FixedTrait::new(16 * ONE_u128, false); - let x = calc_x(x_0, v_0x, t); - assert(x.mag == 900 * ONE_u128, 'invalid mag'); - assert(x.sign == false, 'invalid sign'); - } - - #[test] - fn test_calc_y() { - let y_0 = FixedTrait::new(100 * ONE_u128, false); - let v_0y = FixedTrait::new(50 * ONE_u128, false); - let t = FixedTrait::new(16 * ONE_u128, false); - let g = FixedTrait::new(98 * ONE_u128 / 10, false); - - let y = calc_y(y_0, v_0y, g, t); - assert_precise(y, -6537526099722665092710, 'invalid y', Option::None(())); // -354.4 - assert(y.sign == true, 'invalid sign'); - } -} diff --git a/scripts/build-all.sh b/scripts/build-all.sh new file mode 100644 index 00000000..68fb808e --- /dev/null +++ b/scripts/build-all.sh @@ -0,0 +1,11 @@ +# Scarb dependent crates. +scarb --manifest-path crates/algebra/Scarb.toml build +scarb --manifest-path crates/defi/Scarb.toml build +scarb --manifest-path crates/map/Scarb.toml build +scarb --manifest-path crates/random/Scarb.toml build +scarb --manifest-path crates/rating/Scarb.toml build +scarb --manifest-path crates/security/Scarb.toml build + +# Sozo dependent crates. +sozo build --manifest-path crates/token/Scarb.toml +sozo build --manifest-path crates/governance/Scarb.toml diff --git a/token/Scarb.toml b/token/Scarb.toml deleted file mode 100644 index b7a6ef7d..00000000 --- a/token/Scarb.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "token" -version = "0.0.0" -description = "Implementations of ERC standards for the Dojo framework." -homepage = "https://github.com/dojoengine/origami/tree/token" - -[dependencies] -dojo.workspace = true - -[lib] - -[[target.dojo]]