diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f425a218ad..7f0c610c66 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,39 +80,6 @@ jobs: - uses: arduino/setup-protoc@v2 - run: cargo run --bin sozo -- --manifest-path crates/dojo-core/Scarb.toml test - dojo-erc-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ env.RUST_VERSION }} - - uses: Swatinem/rust-cache@v2 - - uses: arduino/setup-protoc@v2 - - run: cargo run --bin sozo -- --manifest-path crates/dojo-erc/Scarb.toml test - - dojo-defi-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ env.RUST_VERSION }} - - uses: Swatinem/rust-cache@v2 - - uses: arduino/setup-protoc@v2 - - run: cargo run --bin sozo -- --manifest-path crates/dojo-defi/Scarb.toml test - - dojo-primitive-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ env.RUST_VERSION }} - - uses: Swatinem/rust-cache@v2 - - uses: arduino/setup-protoc@v2 - - run: cargo run --bin sozo -- --manifest-path crates/dojo-primitives/Scarb.toml test - dojo-spawn-and-move-example-test: runs-on: ubuntu-latest steps: diff --git a/crates/dojo-defi/.gitignore b/crates/dojo-defi/.gitignore deleted file mode 100644 index 1de565933b..0000000000 --- a/crates/dojo-defi/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target \ No newline at end of file diff --git a/crates/dojo-defi/README.md b/crates/dojo-defi/README.md deleted file mode 100644 index d806f17ce4..0000000000 --- a/crates/dojo-defi/README.md +++ /dev/null @@ -1,173 +0,0 @@ -# Gradual Dutch Auctions (GDA) - -## Introduction - -Gradual Dutch Auctions (GDA) enable efficient sales of assets without relying on liquid markets. GDAs offer a novel solution for selling both non-fungible tokens (NFTs) and fungible tokens through discrete and continuous mechanisms. - -## Discrete GDA - -### Motivation - -Discrete GDAs are perfect for selling NFTs in integer quantities. They offer an efficient way to conduct bulk purchases through a sequence of Dutch auctions. - -### Mechanism - -The process involves holding virtual Dutch auctions for each token, allowing for efficient clearing of batches. Price decay is exponential, controlled by a decay constant, and the starting price increases by a fixed scale factor. - -### Calculating Batch Purchase Prices - -Calculations can be made efficiently for purchasing a batch of auctions, following a given price function. - -## Continuous GDA - -### Motivation - -Continuous GDAs offer a mechanism for selling fungible tokens, allowing for constant rate emissions over time. - -### Mechanism - -The process works by incrementally making more assets available for sale, splitting sales into an infinite sequence of auctions. Various price functions, including exponential decay, can be applied. - -### Calculating Purchase Prices - -It's possible to compute the purchase price for any quantity of tokens gas-efficiently, using specific mathematical expressions. - -## How to Use - -### Discrete Gradual Dutch Auction - -The `DiscreteGDA` structure represents a Gradual Dutch Auction using discrete time steps. Here's how you can use it: - -#### Creating a Discrete GDA - -```rust -let gda = DiscreteGDA { - sold: Fixed::new_unscaled(0), - initial_price: Fixed::new_unscaled(100, false), - scale_factor: FixedTrait::new_unscaled(11, false) / FixedTrait::new_unscaled(10, false), // 1.1 - decay_constant: FixedTrait::new_unscaled(1, false) / FixedTrait::new_unscaled(2, false), // 0.5, -}; -``` - -#### Calculating the Purchase Price - -You can calculate the purchase price for a specific quantity at a given time using the `purchase_price` method. - -```rust -let time_since_start = FixedTrait::new(2, false); // 2 days since the start, it must be scaled to avoid overflow. -let quantity = FixedTrait::new_unscaled(5, false); // Quantity to purchase -let price = gda.purchase_price(time_since_start, quantity); -``` - -### Continuous Gradual Dutch Auction - -The `ContinuousGDA` structure represents a Gradual Dutch Auction using continuous time steps. - -#### Creating a Continuous GDA - -```rust -let gda = ContinuousGDA { - initial_price: FixedTrait::new_unscaled(1000, false), - emission_rate: FixedTrait::ONE(), - decay_constant: FixedTrait::new_unscaled(1, false) / FixedTrait::new_unscaled(2, false), -}; -``` - -#### Calculating the Purchase Price - -Just like with the discrete version, you can calculate the purchase price for a specific quantity at a given time using the `purchase_price` method. - -```rust -let time_since_last = FixedTrait::new(1, false); // 1 day since the last purchase, it must be scaled to avoid overflow. -let quantity = FixedTrait::new_unscaled(3, false); // Quantity to purchase -let price = gda.purchase_price(time_since_last, quantity); -``` - ---- - -These examples demonstrate how to create instances of the `DiscreteGDA` and `ContinuousGDA` structures, and how to utilize their `purchase_price` methods to calculate the price for purchasing specific quantities at given times. - -You'll need to include the `cubit` crate in your project to work with the `Fixed` type and mathematical operations like `exp` and `pow`. Make sure to follow the respective documentation for additional details and proper integration into your project. - -## Conclusion - -GDAs present a powerful tool for selling both fungible and non-fungible tokens in various contexts. They offer efficient, flexible solutions for asset sales, opening doors to innovative applications beyond traditional markets. - -# Variable Rate GDAs (VRGDAs) - -## Overview - -Variable Rate GDAs (VRGDAs) enable the selling of tokens according to a custom schedule, raising or lowering prices based on the sales pace. VRGDA is a generalization of the GDA mechanism. - -## How to Use - -### Linear Variable Rate Gradual Dutch Auction (LinearVRGDA) - -The `LinearVRGDA` struct represents a linear auction where the price decays based on the target price, decay constant, and per-time-unit rate. - -#### Creating a LinearVRGDA instance - -```rust -const _69_42: u128 = 1280572973596917000000; -const _0_31: u128 = 5718490662849961000; - -let auction = LinearVRGDA { - target_price: FixedTrait::new(_69_42, false), - decay_constant: FixedTrait::new(_0_31, false), - per_time_unit: FixedTrait::new_unscaled(2, false), -}; -``` - -#### Calculating Target Sale Time - -```rust -let target_sale_time = auction.get_target_sale_time(sold_quantity); -``` - -#### Calculating VRGDA Price - -```rust -let price = auction.get_vrgda_price(time_since_start, sold_quantity); -``` - -### Logistic Variable Rate Gradual Dutch Auction (LogisticVRGDA) - -The `LogisticVRGDA` struct represents an auction where the price decays according to a logistic function, based on the target price, decay constant, max sellable quantity, and time scale. - -#### Creating a LogisticVRGDA instance - -```rust -const MAX_SELLABLE: u128 = 6392; -const _0_0023: u128 = 42427511369531970; - -let auction = LogisticVRGDA { - target_price: FixedTrait::new(_69_42, false), - decay_constant: FixedTrait::new(_0_31, false), - max_sellable: FixedTrait::new_unscaled(MAX_SELLABLE, false), - time_scale: FixedTrait::new(_0_0023, false), -}; -``` - -#### Calculating Target Sale Time - -```rust -let target_sale_time = auction.get_target_sale_time(sold_quantity); -``` - -#### Calculating VRGDA Price - -```rust -let price = auction.get_vrgda_price(time_since_start, sold_quantity); -``` - -Make sure to import the required dependencies at the beginning of your Cairo file: - -```rust -use cubit::f128::types::fixed::{Fixed, FixedTrait}; -``` - -These examples show you how to create instances of both `LinearVRGDA` and `LogisticVRGDA` and how to use their methods to calculate the target sale time and VRGDA price. - -## Conclusion - -VRGDAs offer a flexible way to issue NFTs on nearly any schedule, enabling seamless purchases at any time. diff --git a/crates/dojo-defi/Scarb.lock b/crates/dojo-defi/Scarb.lock deleted file mode 100644 index 5d0969e80a..0000000000 --- a/crates/dojo-defi/Scarb.lock +++ /dev/null @@ -1,27 +0,0 @@ -# Code generated by scarb DO NOT EDIT. -version = 1 - -[[package]] -name = "cubit" -version = "1.2.0" -source = "git+https://github.com/ponderingdemocritus/cubit#9c3bbdfee7b165ab06ac8cc7046ce4d4c8866bfc" - -[[package]] -name = "dojo" -version = "0.3.11" -dependencies = [ - "dojo_plugin", -] - -[[package]] -name = "dojo_defi" -version = "0.3.11" -dependencies = [ - "cubit", - "dojo", -] - -[[package]] -name = "dojo_plugin" -version = "0.3.11" -source = "git+https://github.com/dojoengine/dojo?tag=v0.3.11#adab82da604669393bf5391439ed4ab1825923d1" diff --git a/crates/dojo-defi/Scarb.toml b/crates/dojo-defi/Scarb.toml deleted file mode 100644 index 8b4fdbf3d1..0000000000 --- a/crates/dojo-defi/Scarb.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -cairo-version = "2.3.1" -description = "Implementations of a defi primitives for the Dojo framework" -name = "dojo_defi" -version = "0.3.11" - -[lib] - -[dependencies] -cubit = { git = "https://github.com/ponderingdemocritus/cubit" } - -dojo = { path = "../dojo-core" } - -[[target.dojo]] diff --git a/crates/dojo-defi/src/dutch_auction.cairo b/crates/dojo-defi/src/dutch_auction.cairo deleted file mode 100644 index 9c0635143f..0000000000 --- a/crates/dojo-defi/src/dutch_auction.cairo +++ /dev/null @@ -1,4 +0,0 @@ -mod gda; -mod vrgda; -mod common; - diff --git a/crates/dojo-defi/src/dutch_auction/common.cairo b/crates/dojo-defi/src/dutch_auction/common.cairo deleted file mode 100644 index f323cb885f..0000000000 --- a/crates/dojo-defi/src/dutch_auction/common.cairo +++ /dev/null @@ -1,27 +0,0 @@ -use cubit::f128::types::fixed::{Fixed, FixedTrait, ONE_u128}; -use dojo_defi::tests::utils::{assert_approx_equal, TOLERANCE}; - -fn to_days_fp(x: Fixed) -> Fixed { - x / FixedTrait::new(86400, false) -} - -fn from_days_fp(x: Fixed) -> Fixed { - x * FixedTrait::new(86400, false) -} - - -#[cfg(test)] -mod test_common { - use cubit::f128::types::fixed::{Fixed, FixedTrait, ONE_u128}; - use dojo_defi::tests::utils::{assert_approx_equal, TOLERANCE}; - - use super::{to_days_fp, from_days_fp}; - - #[test] - #[available_gas(20000000)] - fn test_days_convertions() { - let days = FixedTrait::new(2, false); - assert_approx_equal(days, to_days_fp(from_days_fp(days)), TOLERANCE * 10); - } -} - diff --git a/crates/dojo-defi/src/dutch_auction/gda.cairo b/crates/dojo-defi/src/dutch_auction/gda.cairo deleted file mode 100644 index f2d61b51ec..0000000000 --- a/crates/dojo-defi/src/dutch_auction/gda.cairo +++ /dev/null @@ -1,67 +0,0 @@ -use cubit::f128::math::core::{exp, pow}; -use cubit::f128::types::fixed::{Fixed, FixedTrait}; - -use debug::PrintTrait; - -/// A Gradual Dutch Auction represented using discrete time steps. -/// 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 { - sold: Fixed, - initial_price: Fixed, - scale_factor: Fixed, - decay_constant: Fixed, -} - -#[generate_trait] -impl DiscreteGDAImpl of DiscreteGDATrait { - /// Calculates the purchase price for a given quantity of the item at a specific time. - /// - /// # Arguments - /// - /// * `time_since_start`: Time since the start of the auction in days. - /// * `quantity`: Quantity of the item being purchased. - /// - /// # Returns - /// - /// * A `Fixed` representing the purchase price. - fn purchase_price(self: @DiscreteGDA, time_since_start: Fixed, quantity: Fixed) -> Fixed { - let num1 = *self.initial_price * pow(*self.scale_factor, *self.sold); - let num2 = pow(*self.scale_factor, quantity) - FixedTrait::ONE(); - let den1 = exp(*self.decay_constant * time_since_start); - let den2 = *self.scale_factor - FixedTrait::ONE(); - (num1 * num2) / (den1 * den2) - } -} - -/// 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 { - initial_price: Fixed, - emission_rate: Fixed, - decay_constant: Fixed, -} - -#[generate_trait] -impl ContinuousGDAImpl of ContinuousGDATrait { - /// Calculates the purchase price for a given quantity of the item at a specific time. - /// - /// # Arguments - /// - /// * `time_since_last`: Time since the last purchase in the auction in days. - /// * `quantity`: Quantity of the item being purchased. - /// - /// # Returns - /// - /// * A `Fixed` representing the purchase price. - fn purchase_price(self: @ContinuousGDA, time_since_last: Fixed, quantity: Fixed) -> Fixed { - let num1 = *self.initial_price / *self.decay_constant; - let num2 = exp((*self.decay_constant * quantity) / *self.emission_rate) - FixedTrait::ONE(); - let den = exp(*self.decay_constant * time_since_last); - (num1 * num2) / den - } -} diff --git a/crates/dojo-defi/src/dutch_auction/vrgda.cairo b/crates/dojo-defi/src/dutch_auction/vrgda.cairo deleted file mode 100644 index 3790bfc64a..0000000000 --- a/crates/dojo-defi/src/dutch_auction/vrgda.cairo +++ /dev/null @@ -1,121 +0,0 @@ -use cubit::f128::math::core::{ln, abs, exp}; -use cubit::f128::types::fixed::{Fixed, FixedTrait}; - -/// A Linear Variable Rate Gradual Dutch Auction (VRGDA) struct. -/// 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::Storage)] -struct LinearVRGDA { - target_price: Fixed, - decay_constant: Fixed, - per_time_unit: Fixed, -} - -#[generate_trait] -impl LinearVRGDAImpl of LinearVRGDATrait { - /// Calculates the target sale time based on the quantity sold. - /// - /// # Arguments - /// - /// * `sold`: Quantity sold. - /// - /// # Returns - /// - /// * A `Fixed` representing the target sale time. - fn get_target_sale_time(self: @LinearVRGDA, sold: Fixed) -> Fixed { - sold / *self.per_time_unit - } - - /// Calculates the VRGDA price at a specific time since the auction started. - /// - /// # Arguments - /// - /// * `time_since_start`: Time since the auction started. - /// * `sold`: Quantity sold. - /// - /// # Returns - /// - /// * A `Fixed` representing the price. - fn get_vrgda_price(self: @LinearVRGDA, time_since_start: Fixed, sold: Fixed) -> Fixed { - *self.target_price - * exp( - *self.decay_constant - * (time_since_start - - self.get_target_sale_time(sold + FixedTrait::new(1, false))) - ) - } - - fn get_reverse_vrgda_price(self: @LinearVRGDA, time_since_start: Fixed, sold: Fixed) -> Fixed { - *self.target_price - * exp( - (*self.decay_constant * FixedTrait::new(1, true)) - * (time_since_start - - self.get_target_sale_time(sold + FixedTrait::new(1, false))) - ) - } -} - - -#[derive(Copy, Drop, Serde, starknet::Storage)] -struct LogisticVRGDA { - target_price: Fixed, - decay_constant: Fixed, - max_sellable: Fixed, - time_scale: Fixed, -} - -// A Logistic Variable Rate Gradual Dutch Auction (VRGDA) struct. -/// Represents an auction where the price decays according to a logistic function, -/// based on the target price, decay constant, max sellable quantity, and time scale. -#[generate_trait] -impl LogisticVRGDAImpl of LogisticVRGDATrait { - /// Calculates the target sale time using a logistic function based on the quantity sold. - /// - /// # Arguments - /// - /// * `sold`: Quantity sold. - /// - /// # Returns - /// - /// * A `Fixed` representing the target sale time. - fn get_target_sale_time(self: @LogisticVRGDA, sold: Fixed) -> Fixed { - let logistic_limit = *self.max_sellable + FixedTrait::ONE(); - let logistic_limit_double = logistic_limit * FixedTrait::new_unscaled(2, false); - abs( - ln(logistic_limit_double / (sold + logistic_limit) - FixedTrait::ONE()) - / *self.time_scale - ) - } - - /// Calculates the VRGDA price at a specific time since the auction started, - /// using the logistic function. - /// - /// # Arguments - /// - /// * `time_since_start`: Time since the auction started. - /// * `sold`: Quantity sold. - /// - /// # Returns - /// - /// * A `Fixed` representing the price. - fn get_vrgda_price(self: @LogisticVRGDA, time_since_start: Fixed, sold: Fixed) -> Fixed { - *self.target_price - * exp( - *self.decay_constant - * (time_since_start - - self.get_target_sale_time(sold + FixedTrait::new(1, false))) - ) - } - - fn get_reverse_vrgda_price( - self: @LogisticVRGDA, time_since_start: Fixed, sold: Fixed - ) -> Fixed { - *self.target_price - * exp( - (*self.decay_constant * FixedTrait::new(1, true)) - * (time_since_start - - self.get_target_sale_time(sold + FixedTrait::new(1, false))) - ) - } -} - diff --git a/crates/dojo-defi/src/lib.cairo b/crates/dojo-defi/src/lib.cairo deleted file mode 100644 index b764885332..0000000000 --- a/crates/dojo-defi/src/lib.cairo +++ /dev/null @@ -1,4 +0,0 @@ -mod market; -mod dutch_auction; -mod tests; - diff --git a/crates/dojo-defi/src/market.cairo b/crates/dojo-defi/src/market.cairo deleted file mode 100644 index cb5ccb799c..0000000000 --- a/crates/dojo-defi/src/market.cairo +++ /dev/null @@ -1,3 +0,0 @@ -mod models; -mod systems; -mod constant_product_market; diff --git a/crates/dojo-defi/src/market/constant_product_market.cairo b/crates/dojo-defi/src/market/constant_product_market.cairo deleted file mode 100644 index 1fd4839804..0000000000 --- a/crates/dojo-defi/src/market/constant_product_market.cairo +++ /dev/null @@ -1,211 +0,0 @@ -use starknet::ContractAddress; -use dojo_defi::market::models::Market; -use cubit::f128::types::fixed::{Fixed, FixedTrait}; - -const SCALING_FACTOR: u128 = 10000; - -#[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) -} diff --git a/crates/dojo-defi/src/market/models.cairo b/crates/dojo-defi/src/market/models.cairo deleted file mode 100644 index 1249b0a71a..0000000000 --- a/crates/dojo-defi/src/market/models.cairo +++ /dev/null @@ -1,72 +0,0 @@ -use starknet::ContractAddress; -use dojo::database::schema::{Struct, Ty, SchemaIntrospection, Member, serialize_member}; - -// Cubit fixed point math library -use cubit::f128::types::fixed::Fixed; - -const SCALING_FACTOR: u128 = 10000; - -impl SchemaIntrospectionFixed of SchemaIntrospection { - #[inline(always)] - fn size() -> usize { - 2 - } - - #[inline(always)] - fn layout(ref layout: Array) { - layout.append(128); - layout.append(1); - } - - #[inline(always)] - fn ty() -> Ty { - Ty::Struct( - Struct { - name: 'Fixed', - attrs: array![].span(), - children: array![ - serialize_member( - @Member { name: 'mag', ty: Ty::Primitive('u128'), attrs: array![].span() } - ), - serialize_member( - @Member { name: 'sign', ty: Ty::Primitive('bool'), attrs: array![].span() } - ) - ] - .span() - } - ) - } -} - -#[derive(Model, Copy, Drop, Serde)] -struct Cash { - #[key] - player: ContractAddress, - amount: u128, -} - -#[derive(Model, Copy, Drop, Serde)] -struct Item { - #[key] - player: ContractAddress, - #[key] - item_id: u32, - quantity: u128, -} - -#[derive(Model, Copy, Drop, Serde)] -struct Liquidity { - #[key] - player: ContractAddress, - #[key] - item_id: u32, - shares: Fixed, -} - -#[derive(Model, Copy, Drop, Serde)] -struct Market { - #[key] - item_id: u32, - cash_amount: u128, - item_quantity: u128, -} diff --git a/crates/dojo-defi/src/market/systems.cairo b/crates/dojo-defi/src/market/systems.cairo deleted file mode 100644 index ca37bc768b..0000000000 --- a/crates/dojo-defi/src/market/systems.cairo +++ /dev/null @@ -1,195 +0,0 @@ -use cubit::f128::types::fixed::Fixed; -use dojo::world::IWorldDispatcher; - - -trait ITrade { - fn buy(self: @TContractState, world: IWorldDispatcher, item_id: u32, quantity: u128); - fn sell(self: @TContractState, world: IWorldDispatcher, item_id: u32, quantity: u128); -} - - -#[dojo::contract] -mod Trade { - use dojo_defi::market::models::{Item, Cash, Market}; - use dojo_defi::market::constant_product_market::MarketTrait; - - use super::ITrade; - - - #[external(v0)] - impl TradeImpl of ITrade { - fn buy(self: @ContractState, world: IWorldDispatcher, item_id: u32, quantity: u128) { - - let player = starknet::get_caller_address(); - - let player_cash = get!(world, (player), Cash); - - let market = get!(world, (item_id), Market); - - let cost = market.buy(quantity); - assert(cost <= player_cash.amount, 'not enough cash'); - - // update market - set!( - world, - (Market { - item_id: item_id, - cash_amount: market.cash_amount + cost, - item_quantity: market.item_quantity - quantity, - }) - ); - - // update player cash - set!(world, (Cash { player: player, amount: player_cash.amount - cost })); - - // update player item - let item = get!(world, (player, item_id), Item); - set!( - world, - (Item { player: player, item_id: item_id, quantity: item.quantity + quantity }) - ); - } - - - - fn sell(self: @ContractState, world: IWorldDispatcher, item_id: u32, quantity: u128) { - let player = starknet::get_caller_address(); - - let item = get!(world, (player, item_id), Item); - let player_quantity = item.quantity; - assert(player_quantity >= quantity, 'not enough items'); - - let player_cash = get!(world, (player), Cash); - - let market = get!(world, (item_id), Market); - let payout = market.sell(quantity); - - // update market - set!( - world, - (Market { - item_id: item_id, - cash_amount: market.cash_amount - payout, - item_quantity: market.item_quantity + quantity, - }) - ); - - // update player cash - set!(world, (Cash { player: player, amount: player_cash.amount + payout })); - - // update player item - set!( - world, - (Item { player: player, item_id: item_id, quantity: player_quantity - quantity }) - ); - } - - } - -} - - - -trait ILiquidity { - fn add(self: @TContractState, world: IWorldDispatcher, item_id: u32, amount: u128, quantity: u128); - fn remove(self: @TContractState, world: IWorldDispatcher, item_id: u32, shares: Fixed); -} - - -#[dojo::contract] -mod Liquidity { - use cubit::f128::types::fixed::Fixed; - - use dojo_defi::market::models::{Item, Cash, Market, Liquidity}; - use dojo_defi::market::constant_product_market::MarketTrait; - - use super::ILiquidity; - - #[external(v0)] - impl LiquidityImpl of ILiquidity { - - fn add(self: @ContractState, world: IWorldDispatcher, item_id: u32, amount: u128, quantity: u128) { - let player = starknet::get_caller_address(); - - let item = get!(world, (player, item_id), Item); - let player_quantity = item.quantity; - assert(player_quantity >= quantity, 'not enough items'); - - let player_cash = get!(world, (player), Cash); - assert(amount <= player_cash.amount, 'not enough cash'); - - let market = get!(world, (item_id), Market); - let (cost_cash, cost_quantity, liquidity_shares) = market.add_liquidity(amount, quantity); - - // update market - set!( - world, - (Market { - item_id: item_id, - cash_amount: market.cash_amount + cost_cash, - item_quantity: market.item_quantity + cost_quantity - }) - ); - - // update player cash - set!(world, (Cash { player: player, amount: player_cash.amount - cost_cash })); - - // update player item - set!( - world, - (Item { player: player, item_id: item_id, quantity: player_quantity - cost_quantity }) - ); - - // update player liquidity - let player_liquidity = get!(world, (player, item_id), Liquidity); - set!( - world, - (Liquidity { - player: player, item_id: item_id, shares: player_liquidity.shares + liquidity_shares - }) - ); - } - - - fn remove(self: @ContractState, world: IWorldDispatcher, item_id: u32, shares: Fixed) { - let player = starknet::get_caller_address(); - - let player_liquidity = get!(world, (player, item_id), Liquidity); - assert(player_liquidity.shares >= shares, 'not enough shares'); - - let market = get!(world, (item_id), Market); - let (payout_cash, payout_quantity) = market.remove_liquidity(shares); - - // update market - set!( - world, - (Market { - item_id: item_id, - cash_amount: market.cash_amount - payout_cash, - item_quantity: market.item_quantity - payout_quantity - }) - ); - - // update player cash - let player_cash = get!(world, (player), Cash); - set!(world, (Cash { player: player, amount: player_cash.amount + payout_cash })); - - // update player item - let item = get!(world, (player, item_id), Item); - let player_quantity = item.quantity; - set!( - world, - (Item { player: player, item_id: item_id, quantity: player_quantity + payout_quantity }) - ); - - // update player liquidity - let player_liquidity = get!(world, (player, item_id), Liquidity); - set!( - world, - (Liquidity { - player: player, item_id: item_id, shares: player_liquidity.shares - shares - }) - ); - } - } -} diff --git a/crates/dojo-defi/src/tests.cairo b/crates/dojo-defi/src/tests.cairo deleted file mode 100644 index 178dfdfa03..0000000000 --- a/crates/dojo-defi/src/tests.cairo +++ /dev/null @@ -1,11 +0,0 @@ -#[cfg(test)] -mod discrete_gda_test; -#[cfg(test)] -mod continuous_gda_test; -#[cfg(test)] -mod linear_vrgda_test; -#[cfg(test)] -mod logistic_vrgda_test; -#[cfg(test)] -mod constant_product_market_tests; -mod utils; diff --git a/crates/dojo-defi/src/tests/constant_product_market_tests.cairo b/crates/dojo-defi/src/tests/constant_product_market_tests.cairo deleted file mode 100644 index 4d51200d4d..0000000000 --- a/crates/dojo-defi/src/tests/constant_product_market_tests.cairo +++ /dev/null @@ -1,188 +0,0 @@ -use traits::Into; - -use dojo_defi::market::models::Market; -use dojo_defi::market::constant_product_market::{MarketTrait, SCALING_FACTOR}; -use dojo_defi::tests::utils::{TOLERANCE, assert_approx_equal}; - -use cubit::f128::types::FixedTrait; - -#[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] -#[available_gas(100000)] -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] -#[available_gas(100000)] -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] -#[available_gas(500000)] -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] -#[available_gas(600000)] -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] -#[available_gas(1000000)] -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] -#[available_gas(1000000)] -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/crates/dojo-defi/src/tests/continuous_gda_test.cairo b/crates/dojo-defi/src/tests/continuous_gda_test.cairo deleted file mode 100644 index 0e404c11bb..0000000000 --- a/crates/dojo-defi/src/tests/continuous_gda_test.cairo +++ /dev/null @@ -1,67 +0,0 @@ -use cubit::f128::types::fixed::{Fixed, FixedTrait}; - -use dojo_defi::dutch_auction::gda::{ContinuousGDA, ContinuousGDATrait}; -use dojo_defi::tests::utils::{assert_approx_equal, TOLERANCE}; - -// ipynb with calculations at https://colab.research.google.com/drive/14elIFRXdG3_gyiI43tP47lUC_aClDHfB?usp=sharing -#[test] -#[available_gas(2000000)] -fn test_price_1() { - let auction = ContinuousGDA { - initial_price: FixedTrait::new_unscaled(1000, false), - emission_rate: FixedTrait::ONE(), - decay_constant: FixedTrait::new_unscaled(1, false) / FixedTrait::new_unscaled(2, false), - }; - let expected = FixedTrait::new(22128445337405634000000, false); - let time_since_last = FixedTrait::new_unscaled(10, false); - let quantity = FixedTrait::new_unscaled(9, false); - let price: Fixed = auction.purchase_price(time_since_last, quantity); - assert_approx_equal(price, expected, TOLERANCE) -} - - -#[test] -#[available_gas(2000000)] -fn test_price_2() { - let auction = ContinuousGDA { - initial_price: FixedTrait::new_unscaled(1000, false), - emission_rate: FixedTrait::ONE(), - decay_constant: FixedTrait::new_unscaled(1, false) / FixedTrait::new_unscaled(2, false), - }; - let expected = FixedTrait::new(89774852279643700000, false); - let time_since_last = FixedTrait::new_unscaled(20, false); - let quantity = FixedTrait::new_unscaled(8, false); - let price: Fixed = auction.purchase_price(time_since_last, quantity); - assert_approx_equal(price, expected, TOLERANCE) -} - -#[test] -#[available_gas(2000000)] -fn test_price_3() { - let auction = ContinuousGDA { - initial_price: FixedTrait::new_unscaled(1000, false), - emission_rate: FixedTrait::ONE(), - decay_constant: FixedTrait::new_unscaled(1, false) / FixedTrait::new_unscaled(2, false), - }; - let expected = FixedTrait::new(20393925850936156000, false); - let time_since_last = FixedTrait::new_unscaled(30, false); - let quantity = FixedTrait::new_unscaled(15, false); - let price: Fixed = auction.purchase_price(time_since_last, quantity); - assert_approx_equal(price, expected, TOLERANCE) -} - -#[test] -#[available_gas(2000000)] -fn test_price_4() { - let auction = ContinuousGDA { - initial_price: FixedTrait::new_unscaled(1000, false), - emission_rate: FixedTrait::ONE(), - decay_constant: FixedTrait::new_unscaled(1, false) / FixedTrait::new_unscaled(2, false), - }; - let expected = FixedTrait::new(3028401847768577000000, false); - let time_since_last = FixedTrait::new_unscaled(40, false); - let quantity = FixedTrait::new_unscaled(35, false); - let price: Fixed = auction.purchase_price(time_since_last, quantity); - assert_approx_equal(price, expected, TOLERANCE) -} - diff --git a/crates/dojo-defi/src/tests/discrete_gda_test.cairo b/crates/dojo-defi/src/tests/discrete_gda_test.cairo deleted file mode 100644 index ac0a52dc73..0000000000 --- a/crates/dojo-defi/src/tests/discrete_gda_test.cairo +++ /dev/null @@ -1,79 +0,0 @@ -use cubit::f128::types::fixed::{Fixed, FixedTrait}; - -use dojo_defi::dutch_auction::gda::{DiscreteGDA, DiscreteGDATrait}; -use dojo_defi::tests::utils::{assert_approx_equal, TOLERANCE}; - -#[test] -#[available_gas(2000000)] -fn test_initial_price() { - let auction = DiscreteGDA { - sold: FixedTrait::new_unscaled(0, false), - initial_price: FixedTrait::new_unscaled(1000, false), - scale_factor: FixedTrait::new_unscaled(11, false) / FixedTrait::new_unscaled(10, false), - decay_constant: FixedTrait::new_unscaled(1, false) / FixedTrait::new_unscaled(2, false), - }; - let price = auction.purchase_price(FixedTrait::ZERO(), FixedTrait::ONE()); - assert_approx_equal(price, auction.initial_price, TOLERANCE) -} - -// ipynb with calculations at https://colab.research.google.com/drive/14elIFRXdG3_gyiI43tP47lUC_aClDHfB?usp=sharing -#[test] -#[available_gas(2000000)] -fn test_price_1() { - let auction = DiscreteGDA { - sold: FixedTrait::new_unscaled(1, false), - initial_price: FixedTrait::new_unscaled(1000, false), - scale_factor: FixedTrait::new_unscaled(11, false) / FixedTrait::new_unscaled(10, false), - decay_constant: FixedTrait::new_unscaled(1, false) / FixedTrait::new_unscaled(2, false), - }; - let expected = FixedTrait::new(1856620062541316600000, false); - let price = auction - .purchase_price(FixedTrait::new_unscaled(10, false), FixedTrait::new_unscaled(9, false), ); - assert_approx_equal(price, expected, TOLERANCE) -} - -#[test] -#[available_gas(2000000)] -fn test_price_2() { - let auction = DiscreteGDA { - sold: FixedTrait::new_unscaled(2, false), - initial_price: FixedTrait::new_unscaled(1000, false), - scale_factor: FixedTrait::new_unscaled(11, false) / FixedTrait::new_unscaled(10, false), - decay_constant: FixedTrait::new(1, false) / FixedTrait::new(2, false), - }; - let expected = FixedTrait::new(2042282068795448600000, false); - let price = auction - .purchase_price(FixedTrait::new_unscaled(10, false), FixedTrait::new_unscaled(9, false), ); - assert_approx_equal(price, expected, TOLERANCE) -} - -#[test] -#[available_gas(2000000)] -fn test_price_3() { - let auction = DiscreteGDA { - sold: FixedTrait::new_unscaled(4, false), - initial_price: FixedTrait::new_unscaled(1000, false), - scale_factor: FixedTrait::new_unscaled(11, false) / FixedTrait::new_unscaled(10, false), - decay_constant: FixedTrait::new_unscaled(1, false) / FixedTrait::new_unscaled(2, false), - }; - let expected = FixedTrait::new(2471161303242493000000, false); - let price = auction - .purchase_price(FixedTrait::new_unscaled(10, false), FixedTrait::new_unscaled(9, false), ); - assert_approx_equal(price, expected, TOLERANCE) -} - -#[test] -#[available_gas(2000000)] -fn test_price_4() { - let auction = DiscreteGDA { - sold: FixedTrait::new_unscaled(20, false), - initial_price: FixedTrait::new_unscaled(1000, false), - scale_factor: FixedTrait::new_unscaled(11, false) / FixedTrait::new_unscaled(10, false), - decay_constant: FixedTrait::new_unscaled(1, false) / FixedTrait::new_unscaled(2, false), - }; - let expected = FixedTrait::new(291, false); - let price = auction - .purchase_price(FixedTrait::new_unscaled(85, false), FixedTrait::new_unscaled(1, false), ); - assert_approx_equal(price, expected, TOLERANCE) -} - diff --git a/crates/dojo-defi/src/tests/linear_vrgda_test.cairo b/crates/dojo-defi/src/tests/linear_vrgda_test.cairo deleted file mode 100644 index 3a532d06e6..0000000000 --- a/crates/dojo-defi/src/tests/linear_vrgda_test.cairo +++ /dev/null @@ -1,54 +0,0 @@ -use cubit::f128::types::fixed::{Fixed, FixedTrait}; - -use dojo_defi::dutch_auction::common::{to_days_fp, from_days_fp}; -use dojo_defi::dutch_auction::vrgda::{LinearVRGDA, LinearVRGDATrait}; -use dojo_defi::tests::utils::assert_rel_approx_eq; - -const _69_42: u128 = 1280572973596917000000; -const _0_31: u128 = 5718490662849961000; -const DELTA_0_0005: u128 = 9223372036854776; -const DELTA_0_02: u128 = 368934881474191000; -const DELTA: u128 = 184467440737095; - -#[test] -#[available_gas(2000000)] -fn test_target_price() { - let auction = LinearVRGDA { - target_price: FixedTrait::new(_69_42, false), - decay_constant: FixedTrait::new(_0_31, false), - per_time_unit: FixedTrait::new_unscaled(2, false), - }; - let time = from_days_fp(auction.get_target_sale_time(FixedTrait::new(1, false))); - let cost = auction - .get_vrgda_price(to_days_fp(time + FixedTrait::new(1, false)), FixedTrait::ZERO()); - assert_rel_approx_eq(cost, auction.target_price, FixedTrait::new(DELTA_0_0005, false)); -} - -#[test] -#[available_gas(20000000)] -fn test_pricing_basic() { - let auction = LinearVRGDA { - target_price: FixedTrait::new(_69_42, false), - decay_constant: FixedTrait::new(_0_31, false), - per_time_unit: FixedTrait::new_unscaled(2, false), - }; - let time_delta = FixedTrait::new(10368001, false); // 120 days - let num_mint = FixedTrait::new(239, true); - let cost = auction.get_vrgda_price(time_delta, num_mint); - assert_rel_approx_eq(cost, auction.target_price, FixedTrait::new(DELTA_0_02, false)); -} - -#[test] -#[available_gas(20000000)] -fn test_pricing_basic_reverse() { - let auction = LinearVRGDA { - target_price: FixedTrait::new(_69_42, false), - decay_constant: FixedTrait::new(_0_31, false), - per_time_unit: FixedTrait::new_unscaled(2, false), - }; - let time_delta = FixedTrait::new(10368001, false); // 120 days - let num_mint = FixedTrait::new(239, true); - let cost = auction.get_reverse_vrgda_price(time_delta, num_mint); - assert_rel_approx_eq(cost, auction.target_price, FixedTrait::new(DELTA_0_02, false)); -} - diff --git a/crates/dojo-defi/src/tests/logistic_vrgda_test.cairo b/crates/dojo-defi/src/tests/logistic_vrgda_test.cairo deleted file mode 100644 index c8e7a13cb2..0000000000 --- a/crates/dojo-defi/src/tests/logistic_vrgda_test.cairo +++ /dev/null @@ -1,62 +0,0 @@ -use cubit::f128::types::fixed::{Fixed, FixedTrait}; - -use dojo_defi::dutch_auction::common::{from_days_fp}; -use dojo_defi::dutch_auction::vrgda::{LogisticVRGDA, LogisticVRGDATrait}; -use dojo_defi::tests::utils::assert_rel_approx_eq; - - -use debug::PrintTrait; -const _69_42: u128 = 1280572973596917000000; -const _0_31: u128 = 5718490662849961000; -const DELTA_0_0005: u128 = 9223372036854776; -const DELTA_0_02: u128 = 368934881474191000; -const MAX_SELLABLE: u128 = 6392; -const _0_0023: u128 = 42427511369531970; - -#[test] -#[available_gas(200000000)] -fn test_target_price() { - let auction = LogisticVRGDA { - target_price: FixedTrait::new(_69_42, false), - decay_constant: FixedTrait::new(_0_31, false), - max_sellable: FixedTrait::new_unscaled(MAX_SELLABLE, false), - time_scale: FixedTrait::new(_0_0023, false), - }; - let time = from_days_fp(auction.get_target_sale_time(FixedTrait::new(1, false))); - - let cost = auction.get_vrgda_price(time + FixedTrait::new(1, false), FixedTrait::ZERO()); - assert_rel_approx_eq(cost, auction.target_price, FixedTrait::new(DELTA_0_0005, false)); -} - -#[test] -#[available_gas(200000000)] -fn test_pricing_basic() { - let auction = LogisticVRGDA { - target_price: FixedTrait::new(_69_42, false), - decay_constant: FixedTrait::new(_0_31, false), - max_sellable: FixedTrait::new_unscaled(MAX_SELLABLE, false), - time_scale: FixedTrait::new(_0_0023, false), - }; - let time_delta = FixedTrait::new(10368001, false); - let num_mint = FixedTrait::new(876, false); - - let cost = auction.get_vrgda_price(time_delta, num_mint); - assert_rel_approx_eq(cost, auction.target_price, FixedTrait::new(DELTA_0_02, false)); -} - -#[test] -#[available_gas(200000000)] -fn test_pricing_basic_reverse() { - let auction = LogisticVRGDA { - target_price: FixedTrait::new(_69_42, false), - decay_constant: FixedTrait::new(_0_31, false), - max_sellable: FixedTrait::new_unscaled(MAX_SELLABLE, false), - time_scale: FixedTrait::new(_0_0023, false), - }; - let time_delta = FixedTrait::new(10368001, false); - let num_mint = FixedTrait::new(876, false); - - let cost = auction.get_reverse_vrgda_price(time_delta, num_mint); - assert_rel_approx_eq(cost, auction.target_price, FixedTrait::new(DELTA_0_02, false)); -} - diff --git a/crates/dojo-defi/src/tests/utils.cairo b/crates/dojo-defi/src/tests/utils.cairo deleted file mode 100644 index 470af7258c..0000000000 --- a/crates/dojo-defi/src/tests/utils.cairo +++ /dev/null @@ -1,25 +0,0 @@ -use cubit::f128::types::fixed::{Fixed, FixedTrait}; - -use debug::PrintTrait; - -const TOLERANCE: u128 = 18446744073709550; // 0.001 - -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'); -} - -fn assert_rel_approx_eq(a: Fixed, b: Fixed, max_percent_delta: Fixed) { - if b == FixedTrait::ZERO() { - assert(a == b, 'a should eq ZERO'); - } - let percent_delta = if a > b { - (a - b) / b - } else { - (b - a) / b - }; - - assert(percent_delta < max_percent_delta, 'a ~= b not satisfied'); -} - diff --git a/crates/dojo-erc/.gitignore b/crates/dojo-erc/.gitignore deleted file mode 100644 index 1de565933b..0000000000 --- a/crates/dojo-erc/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target \ No newline at end of file diff --git a/crates/dojo-erc/Scarb.lock b/crates/dojo-erc/Scarb.lock deleted file mode 100644 index 35117caa94..0000000000 --- a/crates/dojo-erc/Scarb.lock +++ /dev/null @@ -1,21 +0,0 @@ -# Code generated by scarb DO NOT EDIT. -version = 1 - -[[package]] -name = "dojo" -version = "0.3.11" -dependencies = [ - "dojo_plugin", -] - -[[package]] -name = "dojo_erc" -version = "0.3.11" -dependencies = [ - "dojo", -] - -[[package]] -name = "dojo_plugin" -version = "0.3.11" -source = "git+https://github.com/dojoengine/dojo?tag=v0.3.11#adab82da604669393bf5391439ed4ab1825923d1" diff --git a/crates/dojo-erc/Scarb.toml b/crates/dojo-erc/Scarb.toml deleted file mode 100644 index 83105a6b8b..0000000000 --- a/crates/dojo-erc/Scarb.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -cairo-version = "2.3.1" -description = "Implementations of ERC standards for the Dojo framework" -name = "dojo_erc" -version = "0.3.11" - -[cairo] -sierra-replace-ids = true - -[lib] - -[dependencies] -dojo = { path = "../dojo-core" } - -[scripts] -build = "sozo build" -migrate = "sozo migrate" -test = "sozo test" - -# Generate targets/manifest with sozo -[[target.dojo]] - - -[tool.dojo.env] -# Katana -rpc_url = "http://localhost:5050" -account_address = "0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973" -private_key = "0x1800000000300000180000000000030000000000003006001800006600" -world_address = "0x4cb5561a3a2a19d14f67f71a9da59c9194e2bbb44e1774260a111094fbd8f39" \ No newline at end of file diff --git a/crates/dojo-erc/src/lib.cairo b/crates/dojo-erc/src/lib.cairo deleted file mode 100644 index 537938a7ba..0000000000 --- a/crates/dojo-erc/src/lib.cairo +++ /dev/null @@ -1,17 +0,0 @@ -mod token { - mod erc20; - mod erc20_models; - mod erc721; - mod erc1155; - -} - -#[cfg(test)] -mod tests { - mod constants; - mod utils; - - mod erc20_tests; - mod erc721_tests; - mod erc1155_tests; -} diff --git a/crates/dojo-erc/src/tests/constants.cairo b/crates/dojo-erc/src/tests/constants.cairo deleted file mode 100644 index 6487fc1836..0000000000 --- a/crates/dojo-erc/src/tests/constants.cairo +++ /dev/null @@ -1,60 +0,0 @@ -use starknet::ContractAddress; -use starknet::contract_address_const; - -const NAME: felt252 = 'NAME'; -const SYMBOL: felt252 = 'SYMBOL'; -const DECIMALS: u8 = 18_u8; -const SUPPLY: u256 = 2000; -const VALUE: u256 = 300; -const ROLE: felt252 = 'ROLE'; -const OTHER_ROLE: felt252 = 'OTHER_ROLE'; -const URI: felt252 = 'URI'; -const TOKEN_ID: u256 = 21; -const TOKEN_AMOUNT: u256 = 42; -const TOKEN_ID_2: u256 = 2; -const TOKEN_AMOUNT_2: u256 = 69; -const PUBKEY: felt252 = 'PUBKEY'; - -fn ADMIN() -> ContractAddress { - contract_address_const::<'ADMIN'>() -} - -fn AUTHORIZED() -> ContractAddress { - contract_address_const::<'AUTHORIZED'>() -} - -fn ZERO() -> ContractAddress { - contract_address_const::<0>() -} - -fn CALLER() -> ContractAddress { - contract_address_const::<'CALLER'>() -} - -fn OWNER() -> ContractAddress { - contract_address_const::<'OWNER'>() -} - -fn NEW_OWNER() -> ContractAddress { - contract_address_const::<'NEW_OWNER'>() -} - -fn OTHER() -> ContractAddress { - contract_address_const::<'OTHER'>() -} - -fn OTHER_ADMIN() -> ContractAddress { - contract_address_const::<'OTHER_ADMIN'>() -} - -fn SPENDER() -> ContractAddress { - contract_address_const::<'SPENDER'>() -} - -fn RECIPIENT() -> ContractAddress { - contract_address_const::<'RECIPIENT'>() -} - -fn OPERATOR() -> ContractAddress { - contract_address_const::<'OPERATOR'>() -} diff --git a/crates/dojo-erc/src/tests/erc1155_tests.cairo b/crates/dojo-erc/src/tests/erc1155_tests.cairo deleted file mode 100644 index 6951695b51..0000000000 --- a/crates/dojo-erc/src/tests/erc1155_tests.cairo +++ /dev/null @@ -1,836 +0,0 @@ -use dojo_erc::tests::utils; -use dojo_erc::tests::constants::{ - ZERO, OWNER, SPENDER, RECIPIENT, OPERATOR, OTHER, NAME, SYMBOL, URI, TOKEN_ID, TOKEN_AMOUNT, - TOKEN_ID_2, TOKEN_AMOUNT_2 -}; - -use dojo_erc::token::erc1155::ERC1155::ERC1155Impl; -use dojo_erc::token::erc1155::ERC1155::ERC1155CamelOnlyImpl; -use dojo_erc::token::erc1155::ERC1155::ERC1155MetadataImpl; -use dojo_erc::token::erc1155::ERC1155::InternalImpl; -use dojo_erc::token::erc1155::ERC1155::WorldInteractionsImpl; -use dojo_erc::token::erc1155::ERC1155::{TransferSingle, TransferBatch, ApprovalForAll}; -use dojo_erc::token::erc1155::ERC1155; -use starknet::ContractAddress; -use starknet::contract_address_const; -use starknet::testing; -use zeroable::Zeroable; -use dojo::test_utils::spawn_test_world; -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - -use dojo_erc::token::erc1155::models::{ - ERC1155Meta, erc_1155_meta, ERC1155OperatorApproval, erc_1155_operator_approval, ERC1155Balance, - erc_1155_balance -}; -use dojo_erc::token::erc1155::ERC1155::_worldContractMemberStateTrait; -use debug::PrintTrait; - -// -// Setup -// - -fn STATE() -> (IWorldDispatcher, ERC1155::ContractState) { - let world = spawn_test_world( - array![ - erc_1155_meta::TEST_CLASS_HASH, - erc_1155_operator_approval::TEST_CLASS_HASH, - erc_1155_balance::TEST_CLASS_HASH, - ] - ); - let mut state = ERC1155::contract_state_for_testing(); - state._world.write(world.contract_address); - - InternalImpl::_mint(ref state, OWNER(), TOKEN_ID, TOKEN_AMOUNT); - utils::drop_event(ZERO()); - - InternalImpl::_mint(ref state, OWNER(), TOKEN_ID_2, TOKEN_AMOUNT_2); - utils::drop_event(ZERO()); - - (world, state) -} - -fn setup() -> ERC1155::ContractState { - let (world, mut state) = STATE(); - ERC1155::constructor(ref state, world.contract_address, NAME, SYMBOL, URI); - utils::drop_event(ZERO()); - state -} - -// -// initializer & constructor -// - -#[test] -#[available_gas(20000000)] -fn test_constructor() { - let (world, mut state) = STATE(); - ERC1155::constructor(ref state, world.contract_address, NAME, SYMBOL, URI); - - assert(ERC1155MetadataImpl::name(@state) == NAME, 'Name should be NAME'); - assert(ERC1155MetadataImpl::symbol(@state) == SYMBOL, 'Symbol should be SYMBOL'); - assert(ERC1155MetadataImpl::uri(@state, 0) == URI, 'Uri should be URI'); -// assert( -// SRC5Impl::supports_interface(@state, erc1155::interface::IERC1155_ID), 'Missing interface ID' -// ); -// assert( -// SRC5Impl::supports_interface(@state, erc1155::interface::IERC1155_METADATA_ID), -// 'missing interface ID' -// ); -// assert( -// SRC5Impl::supports_interface(@state, introspection::interface::ISRC5_ID), -// 'missing interface ID' -// ); -} - -#[test] -#[available_gas(20000000)] -fn test_initializer() { - let (world, mut state) = STATE(); - InternalImpl::initializer(ref state, NAME, SYMBOL, URI); - - assert(ERC1155MetadataImpl::name(@state) == NAME, 'Name should be NAME'); - assert(ERC1155MetadataImpl::symbol(@state) == SYMBOL, 'Symbol should be SYMBOL'); - - assert(ERC1155Impl::balance_of(@state, OWNER(), 0) == 0, 'Balance should be zero'); - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, 'should be TOKEN_AMOUNT' - ); - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID_2) == TOKEN_AMOUNT_2, - 'should be TOKEN_AMOUNT_2' - ); -} - - -// -// Getters -// - -#[test] -#[available_gas(20000000)] -fn test_balance_of() { - let mut state = setup(); - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, 'Should return balance' - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: invalid account',))] -fn test_balance_of_zero() { - let state = setup(); - ERC1155Impl::balance_of(@state, ZERO(), TOKEN_ID); -} - - -#[test] -#[available_gas(20000000)] -fn test_balance_of_batch() { - let mut state = setup(); - - InternalImpl::_mint(ref state, OTHER(), TOKEN_ID_2, TOKEN_AMOUNT_2); - - let balances = ERC1155Impl::balance_of_batch( - @state, array![OWNER(), OTHER()], array![TOKEN_ID, TOKEN_ID_2] - ); - - assert(*balances.at(0) == TOKEN_AMOUNT, 'Should return TOKEN_AMOUNT'); - assert(*balances.at(1) == TOKEN_AMOUNT_2, 'Should return TOKEN_AMOUNT_2'); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: invalid account',))] -fn test_balance_of_batch_zero() { - let state = setup(); - ERC1155Impl::balance_of_batch(@state, array![OTHER(), ZERO()], array![TOKEN_ID_2, TOKEN_ID]); -} - - -// -// set_approval_for_all & _set_approval_for_all -// - -#[test] -#[available_gas(20000000)] -fn test_set_approval_for_all() { - let (world, mut state) = STATE(); - testing::set_caller_address(OWNER()); - - assert(!ERC1155Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), 'Invalid default value'); - - ERC1155Impl::set_approval_for_all(ref state, OPERATOR(), true); - assert_event_approval_for_all(OWNER(), OPERATOR(), true); - - assert( - ERC1155Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), - 'Operator not approved correctly' - ); - - ERC1155Impl::set_approval_for_all(ref state, OPERATOR(), false); - assert_event_approval_for_all(OWNER(), OPERATOR(), false); - - assert( - !ERC1155Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), - 'Approval not revoked correctly' - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: self approval',))] -fn test_set_approval_for_all_owner_equal_operator_true() { - let (world, mut state) = STATE(); - testing::set_caller_address(OWNER()); - ERC1155Impl::set_approval_for_all(ref state, OWNER(), true); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: self approval',))] -fn test_set_approval_for_all_owner_equal_operator_false() { - let (world, mut state) = STATE(); - testing::set_caller_address(OWNER()); - ERC1155Impl::set_approval_for_all(ref state, OWNER(), false); -} - -#[test] -#[available_gas(20000000)] -fn test__set_approval_for_all() { - let (world, mut state) = STATE(); - assert(!ERC1155Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), 'Invalid default value'); - - InternalImpl::_set_approval_for_all(ref state, OWNER(), OPERATOR(), true); - assert_event_approval_for_all(OWNER(), OPERATOR(), true); - - assert( - ERC1155Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), - 'Operator not approved correctly' - ); - - InternalImpl::_set_approval_for_all(ref state, OWNER(), OPERATOR(), false); - assert_event_approval_for_all(OWNER(), OPERATOR(), false); - - assert( - !ERC1155Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), - 'Operator not approved correctly' - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: self approval',))] -fn test__set_approval_for_all_owner_equal_operator_true() { - let (world, mut state) = STATE(); - InternalImpl::_set_approval_for_all(ref state, OWNER(), OWNER(), true); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: self approval',))] -fn test__set_approval_for_all_owner_equal_operator_false() { - let (world, mut state) = STATE(); - InternalImpl::_set_approval_for_all(ref state, OWNER(), OWNER(), false); -} - - -// -// safe_transfer_from & safeTransferFrom -// - -#[test] -#[available_gas(50000000)] -fn test_safe_transfer_from_owner() { - let mut state = setup(); - let id = TOKEN_ID; - let amount = TOKEN_AMOUNT; - let owner = OWNER(); - let recipient = RECIPIENT(); - - assert_state_before_transfer(@state, owner, recipient, id); - - testing::set_caller_address(owner); - ERC1155Impl::safe_transfer_from(ref state, owner, recipient, id, amount, array![]); - assert_event_transfer_single(owner, recipient, id, amount); - - assert_state_after_transfer(@state, owner, recipient, id); -} - -#[test] -#[available_gas(50000000)] -fn test_transferFrom_owner() { - let mut state = setup(); - let id = TOKEN_ID; - let amount = TOKEN_AMOUNT; - let owner = OWNER(); - let recipient = RECIPIENT(); - - assert_state_before_transfer(@state, owner, recipient, id); - - testing::set_caller_address(owner); - ERC1155CamelOnlyImpl::safeTransferFrom(ref state, owner, recipient, id, amount, array![]); - assert_event_transfer_single(owner, recipient, id, amount); - - assert_state_after_transfer(@state, owner, recipient, id); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: wrong sender',))] -fn test_safe_transfer_from_zero() { - let (world, mut state) = STATE(); - ERC1155Impl::safe_transfer_from( - ref state, ZERO(), RECIPIENT(), TOKEN_ID, TOKEN_AMOUNT, array![] - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: wrong sender',))] -fn test_safeTransferFrom_zero() { - let (world, mut state) = STATE(); - ERC1155CamelOnlyImpl::safeTransferFrom( - ref state, ZERO(), RECIPIENT(), TOKEN_ID, TOKEN_AMOUNT, array![] - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: invalid receiver',))] -fn test_safe_transfer_from_to_zero() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC1155Impl::safe_transfer_from(ref state, OWNER(), ZERO(), TOKEN_ID, TOKEN_AMOUNT, array![]); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: invalid receiver',))] -fn test_safeTransferFrom_to_zero() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC1155CamelOnlyImpl::safeTransferFrom( - ref state, OWNER(), ZERO(), TOKEN_ID, TOKEN_AMOUNT, array![] - ); -} - -#[test] -#[available_gas(50000000)] -fn test_safe_transfer_from_to_owner() { - let mut state = setup(); - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, - 'Balance of owner before' - ); - - testing::set_caller_address(OWNER()); - ERC1155Impl::safe_transfer_from(ref state, OWNER(), OWNER(), TOKEN_ID, TOKEN_AMOUNT, array![]); - assert_event_transfer_single(OWNER(), OWNER(), TOKEN_ID, TOKEN_AMOUNT); - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, 'Balance of owner after' - ); -} - -#[test] -#[available_gas(50000000)] -fn test_safeTransferFrom_to_owner() { - let mut state = setup(); - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, - 'Balance of owner before' - ); - - testing::set_caller_address(OWNER()); - ERC1155CamelOnlyImpl::safeTransferFrom( - ref state, OWNER(), OWNER(), TOKEN_ID, TOKEN_AMOUNT, array![] - ); - assert_event_transfer_single(OWNER(), OWNER(), TOKEN_ID, TOKEN_AMOUNT); - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, 'Balance of owner after' - ); -} - -#[test] -#[available_gas(50000000)] -fn test_transfer_from_approved_for_all() { - let mut state = setup(); - let id = TOKEN_ID; - let amount = TOKEN_AMOUNT; - let owner = OWNER(); - let recipient = RECIPIENT(); - - assert_state_before_transfer(@state, owner, recipient, id); - - testing::set_caller_address(owner); - ERC1155Impl::set_approval_for_all(ref state, OPERATOR(), true); - utils::drop_event(ZERO()); - - testing::set_caller_address(OPERATOR()); - ERC1155Impl::safe_transfer_from(ref state, owner, recipient, id, amount, array![]); - assert_event_transfer_single(owner, recipient, id, amount); - - assert_state_after_transfer(@state, owner, recipient, id); -} - -#[test] -#[available_gas(50000000)] -fn test_safeTransferFrom_approved_for_all() { - let mut state = setup(); - let id = TOKEN_ID; - let amount = TOKEN_AMOUNT; - let owner = OWNER(); - let recipient = RECIPIENT(); - - assert_state_before_transfer(@state, owner, recipient, id); - - testing::set_caller_address(owner); - ERC1155CamelOnlyImpl::setApprovalForAll(ref state, OPERATOR(), true); - utils::drop_event(ZERO()); - - testing::set_caller_address(OPERATOR()); - ERC1155CamelOnlyImpl::safeTransferFrom(ref state, owner, recipient, id, amount, array![]); - assert_event_transfer_single(owner, recipient, id, amount); - - assert_state_after_transfer(@state, owner, recipient, id); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: unauthorized caller',))] -fn test_safe_transfer_from_unauthorized() { - let mut state = setup(); - testing::set_caller_address(OTHER()); - ERC1155Impl::safe_transfer_from( - ref state, OWNER(), RECIPIENT(), TOKEN_ID, TOKEN_AMOUNT, array![] - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: unauthorized caller',))] -fn test_safeTransferFrom_unauthorized() { - let mut state = setup(); - testing::set_caller_address(OTHER()); - ERC1155CamelOnlyImpl::safeTransferFrom( - ref state, OWNER(), RECIPIENT(), TOKEN_ID, TOKEN_AMOUNT, array![] - ); -} - - -// -// safe_batch_transfer_from & safeBatchTransferFrom -// - -#[test] -#[available_gas(50000000)] -fn test_safe_batch_transfer_from_owner() { - let mut state = setup(); - let owner = OWNER(); - let recipient = RECIPIENT(); - - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - assert_state_before_batch_transfer(@state, owner, recipient); - - testing::set_caller_address(owner); - ERC1155Impl::safe_batch_transfer_from( - ref state, owner, recipient, ids.clone(), amounts.clone(), array![] - ); - assert_event_transfer_batch(owner, recipient, ids, amounts); - - assert_state_after_batch_transfer(@state, owner, recipient); -} - -#[test] -#[available_gas(50000000)] -fn test_safeBatchTransferFrom_owner() { - let mut state = setup(); - let owner = OWNER(); - let recipient = RECIPIENT(); - - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - assert_state_before_batch_transfer(@state, owner, recipient); - - testing::set_caller_address(owner); - ERC1155CamelOnlyImpl::safeBatchTransferFrom( - ref state, owner, recipient, ids.clone(), amounts.clone(), array![] - ); - assert_event_transfer_batch(owner, recipient, ids, amounts); - - assert_state_after_batch_transfer(@state, owner, recipient); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: wrong sender',))] -fn test_safe_batch_transfer_from_zero() { - let (world, mut state) = STATE(); - - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - ERC1155Impl::safe_batch_transfer_from(ref state, ZERO(), RECIPIENT(), ids, amounts, array![]); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: wrong sender',))] -fn test_safeBatchTransferFrom_zero() { - let (world, mut state) = STATE(); - - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - ERC1155CamelOnlyImpl::safeBatchTransferFrom( - ref state, ZERO(), RECIPIENT(), ids, amounts, array![] - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: invalid receiver',))] -fn test_safe_batch_transfer_from_to_zero() { - let (world, mut state) = STATE(); - - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - ERC1155Impl::safe_batch_transfer_from(ref state, OWNER(), ZERO(), ids, amounts, array![]); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: invalid receiver',))] -fn test_safeBatchTransferFrom_to_zero() { - let (world, mut state) = STATE(); - - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - ERC1155Impl::safe_batch_transfer_from(ref state, OWNER(), ZERO(), ids, amounts, array![]); -} - -#[test] -#[available_gas(50000000)] -fn test_safe_batch_transfer_from_to_owner() { - let mut state = setup(); - - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, - 'Balance of owner before1' - ); - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID_2) == TOKEN_AMOUNT_2, - 'Balance of owner before1' - ); - - testing::set_caller_address(OWNER()); - ERC1155Impl::safe_batch_transfer_from( - ref state, OWNER(), OWNER(), ids.clone(), amounts.clone(), array![] - ); - assert_event_transfer_batch(OWNER(), OWNER(), ids, amounts); - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, - 'Balance of owner after1' - ); - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID_2) == TOKEN_AMOUNT_2, - 'Balance of owner after2' - ); -} - -#[test] -#[available_gas(50000000)] -fn test_safeBatchTransferFrom_to_owner() { - let mut state = setup(); - - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, - 'Balance of owner before1' - ); - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID_2) == TOKEN_AMOUNT_2, - 'Balance of owner before1' - ); - - testing::set_caller_address(OWNER()); - ERC1155CamelOnlyImpl::safeBatchTransferFrom( - ref state, OWNER(), OWNER(), ids.clone(), amounts.clone(), array![] - ); - assert_event_transfer_batch(OWNER(), OWNER(), ids, amounts); - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, - 'Balance of owner after1' - ); - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID_2) == TOKEN_AMOUNT_2, - 'Balance of owner after2' - ); -} - -#[test] -#[available_gas(50000000)] -fn test_batch_transfer_from_approved_for_all() { - let mut state = setup(); - let owner = OWNER(); - let recipient = RECIPIENT(); - - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - assert_state_before_batch_transfer(@state, owner, recipient); - - testing::set_caller_address(owner); - ERC1155Impl::set_approval_for_all(ref state, OPERATOR(), true); - utils::drop_event(ZERO()); - - testing::set_caller_address(OPERATOR()); - ERC1155Impl::safe_batch_transfer_from( - ref state, owner, recipient, ids.clone(), amounts.clone(), array![] - ); - assert_event_transfer_batch(owner, recipient, ids, amounts); - - assert_state_after_batch_transfer(@state, owner, recipient); -} - -#[test] -#[available_gas(50000000)] -fn test_safeBatchTransferFrom_approved_for_all() { - let mut state = setup(); - let owner = OWNER(); - let recipient = RECIPIENT(); - - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - assert_state_before_batch_transfer(@state, owner, recipient); - - testing::set_caller_address(owner); - ERC1155CamelOnlyImpl::setApprovalForAll(ref state, OPERATOR(), true); - utils::drop_event(ZERO()); - - testing::set_caller_address(OPERATOR()); - ERC1155CamelOnlyImpl::safeBatchTransferFrom( - ref state, owner, recipient, ids.clone(), amounts.clone(), array![] - ); - assert_event_transfer_batch(owner, recipient, ids, amounts); - - assert_state_after_batch_transfer(@state, owner, recipient); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: unauthorized caller',))] -fn test_safe_batch_transfer_from_unauthorized() { - let mut state = setup(); - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - testing::set_caller_address(OTHER()); - ERC1155Impl::safe_batch_transfer_from(ref state, OWNER(), RECIPIENT(), ids, amounts, array![]); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: unauthorized caller',))] -fn test_safeBatchTransferFrom_unauthorized() { - let mut state = setup(); - let ids = array![TOKEN_ID, TOKEN_ID_2]; - let amounts = array![TOKEN_AMOUNT, TOKEN_AMOUNT_2]; - - testing::set_caller_address(OTHER()); - ERC1155CamelOnlyImpl::safeBatchTransferFrom( - ref state, OWNER(), RECIPIENT(), ids, amounts, array![] - ); -} - -// -// _mint -// - -#[test] -#[available_gas(20000000)] -fn test__mint() { - let (world, mut state) = STATE(); - let recipient = RECIPIENT(); - - assert( - ERC1155Impl::balance_of(@state, recipient, TOKEN_ID_2) == 0, 'Balance of recipient before' - ); - - InternalImpl::_mint(ref state, recipient, TOKEN_ID_2, TOKEN_AMOUNT_2); - assert_event_transfer_single(ZERO(), recipient, TOKEN_ID_2, TOKEN_AMOUNT_2); - - assert( - ERC1155Impl::balance_of(@state, recipient, TOKEN_ID_2) == TOKEN_AMOUNT_2, - 'Balance of recipient after' - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: invalid receiver',))] -fn test__mint_to_zero() { - let (world, mut state) = STATE(); - InternalImpl::_mint(ref state, ZERO(), TOKEN_ID, TOKEN_AMOUNT); -} - - -// -// _burn -// - -#[test] -#[available_gas(20000000)] -fn test__burn() { - let mut state = setup(); - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, - 'Balance of owner before' - ); - - testing::set_caller_address(OWNER()); - InternalImpl::_burn(ref state, TOKEN_ID, 2); - assert_event_transfer_single(OWNER(), ZERO(), TOKEN_ID, 2); - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT - 2, - 'Balance of owner after' - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC1155: insufficient balance',))] -fn test__burn_more_than_balance() { - let mut state = setup(); - - assert( - ERC1155Impl::balance_of(@state, OWNER(), TOKEN_ID) == TOKEN_AMOUNT, - 'Balance of owner before' - ); - InternalImpl::_burn(ref state, TOKEN_ID, TOKEN_AMOUNT + 1); -} - - -// -// Helpers -// - -fn assert_state_before_transfer( - state: @ERC1155::ContractState, owner: ContractAddress, recipient: ContractAddress, id: u256, -) { - assert(ERC1155Impl::balance_of(state, owner, id) == TOKEN_AMOUNT, 'Balance of owner before'); - assert(ERC1155Impl::balance_of(state, recipient, id) == 0, 'Balance of recipient before'); -} - -fn assert_state_after_transfer( - state: @ERC1155::ContractState, owner: ContractAddress, recipient: ContractAddress, id: u256 -) { - assert(ERC1155Impl::balance_of(state, owner, id) == 0, 'Balance of owner after'); - assert( - ERC1155Impl::balance_of(state, recipient, id) == TOKEN_AMOUNT, 'Balance of recipient after' - ); -} - -fn assert_state_before_batch_transfer( - state: @ERC1155::ContractState, owner: ContractAddress, recipient: ContractAddress -) { - assert( - ERC1155Impl::balance_of(state, owner, TOKEN_ID) == TOKEN_AMOUNT, 'Balance of owner before1' - ); - assert( - ERC1155Impl::balance_of(state, owner, TOKEN_ID_2) == TOKEN_AMOUNT_2, - 'Balance of owner before2' - ); - assert( - ERC1155Impl::balance_of(state, recipient, TOKEN_ID) == 0, 'Balance of recipient before1' - ); - assert( - ERC1155Impl::balance_of(state, recipient, TOKEN_ID_2) == 0, 'Balance of recipient before2' - ); -} - -fn assert_state_after_batch_transfer( - state: @ERC1155::ContractState, owner: ContractAddress, recipient: ContractAddress -) { - assert(ERC1155Impl::balance_of(state, owner, TOKEN_ID) == 0, 'Balance of owner after1'); - assert(ERC1155Impl::balance_of(state, owner, TOKEN_ID_2) == 0, 'Balance of owner after2'); - assert( - ERC1155Impl::balance_of(state, recipient, TOKEN_ID) == TOKEN_AMOUNT, - 'Balance of recipient after1' - ); - assert( - ERC1155Impl::balance_of(state, recipient, TOKEN_ID_2) == TOKEN_AMOUNT_2, - 'Balance of recipient after2' - ); -} - - -// -// events -// - -fn assert_event_approval_for_all( - owner: ContractAddress, operator: ContractAddress, approved: bool -) { - let event = utils::pop_log::(ZERO()).unwrap(); - assert(event.owner == owner, 'Invalid `owner`'); - assert(event.operator == operator, 'Invalid `operator`'); - assert(event.approved == approved, 'Invalid `approved`'); - utils::assert_no_events_left(ZERO()); -} - -fn assert_event_transfer_single( - from: ContractAddress, to: ContractAddress, id: u256, amount: u256 -) { - let event = utils::pop_log::(ZERO()).unwrap(); - assert(event.from == from, 'Invalid `from`'); - assert(event.to == to, 'Invalid `to`'); - assert(event.id == id, 'Invalid `id`'); - assert(event.value == amount, 'Invalid `amount`'); - utils::assert_no_events_left(ZERO()); -} - -fn assert_event_transfer_batch( - from: ContractAddress, to: ContractAddress, ids: Array, amounts: Array -) { - let event = utils::pop_log::(ZERO()).unwrap(); - assert(event.from == from, 'Invalid `from`'); - assert(event.to == to, 'Invalid `to`'); - assert(event.ids.len() == event.values.len(), 'Invalid array length'); - - let mut i = 0; - - loop { - if i == event.ids.len() { - break; - } - - assert(event.ids.at(i) == ids.at(i), 'Invalid `id`'); - assert(event.values.at(i) == amounts.at(i), 'Invalid `id`'); - - i += 1; - }; - - utils::assert_no_events_left(ZERO()); -} - diff --git a/crates/dojo-erc/src/tests/erc20_tests.cairo b/crates/dojo-erc/src/tests/erc20_tests.cairo deleted file mode 100644 index 669cfc7c4d..0000000000 --- a/crates/dojo-erc/src/tests/erc20_tests.cairo +++ /dev/null @@ -1,546 +0,0 @@ -use integer::BoundedInt; -use integer::u256; -use integer::u256_from_felt252; -use dojo_erc::tests::utils; -use dojo_erc::tests::constants::{ - ZERO, OWNER, SPENDER, RECIPIENT, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE -}; -use dojo_erc::token::erc20::ERC20::Approval; -use dojo_erc::token::erc20::ERC20::ERC20Impl; -use dojo_erc::token::erc20::ERC20::InternalImpl; -use dojo_erc::token::erc20::ERC20::Transfer; -use dojo_erc::token::erc20::ERC20; -use starknet::ContractAddress; -use starknet::contract_address_const; -use starknet::testing; -use zeroable::Zeroable; -use dojo::test_utils::spawn_test_world; -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - -use dojo_erc::token::erc20_models::{ - ERC20Allowance, erc_20_allowance, ERC20Balance, erc_20_balance, ERC20Meta, erc_20_meta -}; -use dojo_erc::token::erc20::ERC20::_worldContractMemberStateTrait; -use debug::PrintTrait; - -// -// Setup -// - -fn STATE() -> (IWorldDispatcher, ERC20::ContractState) { - let world = spawn_test_world( - array![ - erc_20_allowance::TEST_CLASS_HASH, - erc_20_balance::TEST_CLASS_HASH, - erc_20_meta::TEST_CLASS_HASH, - ] - ); - let mut state = ERC20::contract_state_for_testing(); - state._world.write(world.contract_address); - (world, state) -} - -fn setup() -> ERC20::ContractState { - let (world, mut state) = STATE(); - ERC20::constructor(ref state, world.contract_address, NAME, SYMBOL, SUPPLY, OWNER()); - utils::drop_event(ZERO()); - state -} - -// -// initializer & constructor -// - -#[test] -#[available_gas(25000000)] -fn test_initializer() { - let (world, mut state) = STATE(); - InternalImpl::initializer(ref state, NAME, SYMBOL); - - assert(ERC20Impl::name(@state) == NAME, 'Name should be NAME'); - assert(ERC20Impl::symbol(@state) == SYMBOL, 'Symbol should be SYMBOL'); - assert(ERC20Impl::decimals(@state) == DECIMALS, 'Decimals should be 18'); - assert(ERC20Impl::total_supply(@state) == 0, 'Supply should eq 0'); -} - - -#[test] -#[available_gas(25000000)] -fn test_constructor() { - let (world, mut state) = STATE(); - ERC20::constructor(ref state, world.contract_address, NAME, SYMBOL, SUPPLY, OWNER()); - - assert_only_event_transfer(ZERO(), OWNER(), SUPPLY); - - assert(ERC20Impl::balance_of(@state, OWNER()) == SUPPLY, 'Should eq inital_supply'); - assert(ERC20Impl::total_supply(@state) == SUPPLY, 'Should eq inital_supply'); - assert(ERC20Impl::name(@state) == NAME, 'Name should be NAME'); - assert(ERC20Impl::symbol(@state) == SYMBOL, 'Symbol should be SYMBOL'); - assert(ERC20Impl::decimals(@state) == DECIMALS, 'Decimals should be 18'); -} - -// -// Getters -// - -#[test] -#[available_gas(25000000)] -fn test_total_supply() { - let (world, mut state) = STATE(); - InternalImpl::_mint(ref state, OWNER(), SUPPLY); - assert(ERC20Impl::total_supply(@state) == SUPPLY, 'Should eq SUPPLY'); -} - -#[test] -#[available_gas(25000000)] -fn test_balance_of() { - let (world, mut state) = STATE(); - InternalImpl::_mint(ref state, OWNER(), SUPPLY); - assert(ERC20Impl::balance_of(@state, OWNER()) == SUPPLY, 'Should eq SUPPLY'); -} - - -#[test] -#[available_gas(25000000)] -fn test_allowance() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20Impl::approve(ref state, SPENDER(), VALUE); - - assert(ERC20Impl::allowance(@state, OWNER(), SPENDER()) == VALUE, 'Should eq VALUE'); -} - -// -// approve & _approve -// - -#[test] -#[available_gas(25000000)] -fn test_approve() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - assert(ERC20Impl::approve(ref state, SPENDER(), VALUE), 'Should return true'); - - assert_only_event_approval(OWNER(), SPENDER(), VALUE); - assert( - ERC20Impl::allowance(@state, OWNER(), SPENDER()) == VALUE, 'Spender not approved correctly' - ); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: approve from 0',))] -fn test_approve_from_zero() { - let mut state = setup(); - ERC20Impl::approve(ref state, SPENDER(), VALUE); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: approve to 0',))] -fn test_approve_to_zero() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20Impl::approve(ref state, Zeroable::zero(), VALUE); -} - -#[test] -#[available_gas(25000000)] -fn test__approve() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - InternalImpl::_approve(ref state, OWNER(), SPENDER(), VALUE); - - assert_only_event_approval(OWNER(), SPENDER(), VALUE); - assert( - ERC20Impl::allowance(@state, OWNER(), SPENDER()) == VALUE, 'Spender not approved correctly' - ); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: approve from 0',))] -fn test__approve_from_zero() { - let mut state = setup(); - InternalImpl::_approve(ref state, Zeroable::zero(), SPENDER(), VALUE); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: approve to 0',))] -fn test__approve_to_zero() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - InternalImpl::_approve(ref state, OWNER(), Zeroable::zero(), VALUE); -} - -// -// transfer & _transfer -// - -#[test] -#[available_gas(25000000)] -fn test_transfer() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - assert(ERC20Impl::transfer(ref state, RECIPIENT(), VALUE), 'Should return true'); - - assert_only_event_transfer(OWNER(), RECIPIENT(), VALUE); - assert(ERC20Impl::balance_of(@state, RECIPIENT()) == VALUE, 'Balance should eq VALUE'); - assert(ERC20Impl::balance_of(@state, OWNER()) == SUPPLY - VALUE, 'Should eq supply - VALUE'); - assert(ERC20Impl::total_supply(@state) == SUPPLY, 'Total supply should not change'); -} - -#[test] -#[available_gas(25000000)] -fn test__transfer() { - let mut state = setup(); - - InternalImpl::_transfer(ref state, OWNER(), RECIPIENT(), VALUE); - - assert_only_event_transfer(OWNER(), RECIPIENT(), VALUE); - assert(ERC20Impl::balance_of(@state, RECIPIENT()) == VALUE, 'Balance should eq amount'); - assert(ERC20Impl::balance_of(@state, OWNER()) == SUPPLY - VALUE, 'Should eq supply - amount'); - assert(ERC20Impl::total_supply(@state) == SUPPLY, 'Total supply should not change'); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('u256_sub Overflow',))] -fn test__transfer_not_enough_balance() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - - let balance_plus_one = SUPPLY + 1; - InternalImpl::_transfer(ref state, OWNER(), RECIPIENT(), balance_plus_one); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: transfer from 0',))] -fn test__transfer_from_zero() { - let mut state = setup(); - InternalImpl::_transfer(ref state, Zeroable::zero(), RECIPIENT(), VALUE); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: transfer to 0',))] -fn test__transfer_to_zero() { - let mut state = setup(); - InternalImpl::_transfer(ref state, OWNER(), Zeroable::zero(), VALUE); -} - -// -// transfer_from -// - -#[test] -#[available_gas(30000000)] -fn test_transfer_from() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20Impl::approve(ref state, SPENDER(), VALUE); - utils::drop_event(ZERO()); - - testing::set_caller_address(SPENDER()); - assert(ERC20Impl::transfer_from(ref state, OWNER(), RECIPIENT(), VALUE), 'Should return true'); - - assert_event_approval(OWNER(), SPENDER(), 0); - assert_only_event_transfer(OWNER(), RECIPIENT(), VALUE); - - assert(ERC20Impl::balance_of(@state, RECIPIENT()) == VALUE, 'Should eq amount'); - assert(ERC20Impl::balance_of(@state, OWNER()) == SUPPLY - VALUE, 'Should eq suppy - amount'); - assert(ERC20Impl::allowance(@state, OWNER(), SPENDER()) == 0, 'Should eq 0'); - assert(ERC20Impl::total_supply(@state) == SUPPLY, 'Total supply should not change'); -} - -#[test] -#[available_gas(25000000)] -fn test_transfer_from_doesnt_consume_infinite_allowance() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20Impl::approve(ref state, SPENDER(), BoundedInt::max()); - - testing::set_caller_address(SPENDER()); - ERC20Impl::transfer_from(ref state, OWNER(), RECIPIENT(), VALUE); - - assert( - ERC20Impl::allowance(@state, OWNER(), SPENDER()) == BoundedInt::max(), - 'Allowance should not change' - ); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('u256_sub Overflow',))] -fn test_transfer_from_greater_than_allowance() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20Impl::approve(ref state, SPENDER(), VALUE); - - testing::set_caller_address(SPENDER()); - let allowance_plus_one = VALUE + 1; - ERC20Impl::transfer_from(ref state, OWNER(), RECIPIENT(), allowance_plus_one); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: transfer to 0',))] -fn test_transfer_from_to_zero_address() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20Impl::approve(ref state, SPENDER(), VALUE); - - testing::set_caller_address(SPENDER()); - ERC20Impl::transfer_from(ref state, OWNER(), Zeroable::zero(), VALUE); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('u256_sub Overflow',))] -fn test_transfer_from_from_zero_address() { - let mut state = setup(); - ERC20Impl::transfer_from(ref state, Zeroable::zero(), RECIPIENT(), VALUE); -} - -// -// increase_allowance & increaseAllowance -// - -#[test] -#[available_gas(25000000)] -fn test_increase_allowance() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20Impl::approve(ref state, SPENDER(), VALUE); - utils::drop_event(ZERO()); - - assert(ERC20::increase_allowance(ref state, SPENDER(), VALUE), 'Should return true'); - - assert_only_event_approval(OWNER(), SPENDER(), VALUE * 2); - assert(ERC20Impl::allowance(@state, OWNER(), SPENDER()) == VALUE * 2, 'Should be amount * 2'); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: approve to 0',))] -fn test_increase_allowance_to_zero_address() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20::increase_allowance(ref state, Zeroable::zero(), VALUE); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: approve from 0',))] -fn test_increase_allowance_from_zero_address() { - let mut state = setup(); - ERC20::increase_allowance(ref state, SPENDER(), VALUE); -} - -#[test] -#[available_gas(25000000)] -fn test_increaseAllowance() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20Impl::approve(ref state, SPENDER(), VALUE); - utils::drop_event(ZERO()); - - assert(ERC20::increaseAllowance(ref state, SPENDER(), VALUE), 'Should return true'); - - assert_only_event_approval(OWNER(), SPENDER(), 2 * VALUE); - assert(ERC20Impl::allowance(@state, OWNER(), SPENDER()) == VALUE * 2, 'Should be amount * 2'); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: approve to 0',))] -fn test_increaseAllowance_to_zero_address() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20::increaseAllowance(ref state, Zeroable::zero(), VALUE); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: approve from 0',))] -fn test_increaseAllowance_from_zero_address() { - let mut state = setup(); - ERC20::increaseAllowance(ref state, SPENDER(), VALUE); -} - -// -// decrease_allowance & decreaseAllowance -// - -#[test] -#[available_gas(25000000)] -fn test_decrease_allowance() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20Impl::approve(ref state, SPENDER(), VALUE); - utils::drop_event(ZERO()); - - assert(ERC20::decrease_allowance(ref state, SPENDER(), VALUE), 'Should return true'); - - assert_only_event_approval(OWNER(), SPENDER(), 0); - assert(ERC20Impl::allowance(@state, OWNER(), SPENDER()) == VALUE - VALUE, 'Should be 0'); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('u256_sub Overflow',))] -fn test_decrease_allowance_to_zero_address() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20::decrease_allowance(ref state, Zeroable::zero(), VALUE); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('u256_sub Overflow',))] -fn test_decrease_allowance_from_zero_address() { - let mut state = setup(); - ERC20::decrease_allowance(ref state, SPENDER(), VALUE); -} - -#[test] -#[available_gas(25000000)] -fn test_decreaseAllowance() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20Impl::approve(ref state, SPENDER(), VALUE); - utils::drop_event(ZERO()); - - assert(ERC20::decreaseAllowance(ref state, SPENDER(), VALUE), 'Should return true'); - - assert_only_event_approval(OWNER(), SPENDER(), 0); - assert(ERC20Impl::allowance(@state, OWNER(), SPENDER()) == VALUE - VALUE, 'Should be 0'); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('u256_sub Overflow',))] -fn test_decreaseAllowance_to_zero_address() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC20::decreaseAllowance(ref state, Zeroable::zero(), VALUE); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('u256_sub Overflow',))] -fn test_decreaseAllowance_from_zero_address() { - let mut state = setup(); - ERC20::decreaseAllowance(ref state, SPENDER(), VALUE); -} - -// -// _spend_allowance -// - -#[test] -#[available_gas(25000000)] -fn test__spend_allowance_not_unlimited() { - let mut state = setup(); - - InternalImpl::_approve(ref state, OWNER(), SPENDER(), SUPPLY); - utils::drop_event(ZERO()); - - InternalImpl::_spend_allowance(ref state, OWNER(), SPENDER(), VALUE); - - assert_only_event_approval(OWNER(), SPENDER(), SUPPLY - VALUE); - assert( - ERC20Impl::allowance(@state, OWNER(), SPENDER()) == SUPPLY - VALUE, - 'Should eq supply - amount' - ); -} - -#[test] -#[available_gas(25000000)] -fn test__spend_allowance_unlimited() { - let mut state = setup(); - InternalImpl::_approve(ref state, OWNER(), SPENDER(), BoundedInt::max()); - - let max_minus_one: u256 = BoundedInt::max() - 1; - InternalImpl::_spend_allowance(ref state, OWNER(), SPENDER(), max_minus_one); - - assert( - ERC20Impl::allowance(@state, OWNER(), SPENDER()) == BoundedInt::max(), - 'Allowance should not change' - ); -} - -// -// _mint -// - -#[test] -#[available_gas(25000000)] -fn test__mint() { - let (world, mut state) = STATE(); - InternalImpl::_mint(ref state, OWNER(), VALUE); - assert_only_event_transfer(ZERO(), OWNER(), VALUE); - assert(ERC20Impl::balance_of(@state, OWNER()) == VALUE, 'Should eq amount'); - assert(ERC20Impl::total_supply(@state) == VALUE, 'Should eq total supply'); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: mint to 0',))] -fn test__mint_to_zero() { - let (world, mut state) = STATE(); - InternalImpl::_mint(ref state, Zeroable::zero(), VALUE); -} - -// -// _burn -// - -#[test] -#[available_gas(25000000)] -fn test__burn() { - let mut state = setup(); - InternalImpl::_burn(ref state, OWNER(), VALUE); - - assert_only_event_transfer(OWNER(), ZERO(), VALUE); - assert(ERC20Impl::total_supply(@state) == SUPPLY - VALUE, 'Should eq supply - amount'); - assert(ERC20Impl::balance_of(@state, OWNER()) == SUPPLY - VALUE, 'Should eq supply - amount'); -} - -#[test] -#[available_gas(25000000)] -#[should_panic(expected: ('ERC20: burn from 0',))] -fn test__burn_from_zero() { - let mut state = setup(); - InternalImpl::_burn(ref state, Zeroable::zero(), VALUE); -} - -// -// Helpers -// - -fn assert_event_approval(owner: ContractAddress, spender: ContractAddress, value: u256) { - let event = utils::pop_log::(ZERO()).unwrap(); - assert(event.owner == owner, 'Invalid `owner`'); - assert(event.spender == spender, 'Invalid `spender`'); - assert(event.value == value, 'Invalid `value`'); -} - -fn assert_only_event_approval(owner: ContractAddress, spender: ContractAddress, value: u256) { - assert_event_approval(owner, spender, value); - utils::assert_no_events_left(ZERO()); -} - -fn assert_event_transfer(from: ContractAddress, to: ContractAddress, value: u256) { - let event = utils::pop_log::(ZERO()).unwrap(); - assert(event.from == from, 'Invalid `from`'); - assert(event.to == to, 'Invalid `to`'); - assert(event.value == value, 'Invalid `value`'); -} - -fn assert_only_event_transfer(from: ContractAddress, to: ContractAddress, value: u256) { - assert_event_transfer(from, to, value); - utils::assert_no_events_left(ZERO()); -} diff --git a/crates/dojo-erc/src/tests/erc721_tests.cairo b/crates/dojo-erc/src/tests/erc721_tests.cairo deleted file mode 100644 index 415db0ff16..0000000000 --- a/crates/dojo-erc/src/tests/erc721_tests.cairo +++ /dev/null @@ -1,1453 +0,0 @@ -use integer::u256; -use integer::u256_from_felt252; -use dojo_erc::tests::utils; -use dojo_erc::tests::constants::{ - ZERO, OWNER, SPENDER, RECIPIENT, OPERATOR, OTHER, NAME, SYMBOL, URI, TOKEN_ID -}; - -use dojo_erc::token::erc721::ERC721::ERC721Impl; -use dojo_erc::token::erc721::ERC721::ERC721CamelOnlyImpl; -use dojo_erc::token::erc721::ERC721::ERC721MetadataImpl; -use dojo_erc::token::erc721::ERC721::InternalImpl; -use dojo_erc::token::erc721::ERC721::WorldInteractionsImpl; -use dojo_erc::token::erc721::ERC721::{Approval, ApprovalForAll, Transfer}; -use dojo_erc::token::erc721::ERC721; -use starknet::ContractAddress; -use starknet::contract_address_const; -use starknet::testing; -use zeroable::Zeroable; -use dojo::test_utils::spawn_test_world; -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - -use dojo_erc::token::erc721::models::{ - ERC721Meta, erc_721_meta, ERC721OperatorApproval, erc_721_operator_approval, ERC721Owner, - erc_721_owner, ERC721Balance, erc_721_balance, ERC721TokenApproval, erc_721_token_approval -}; -use dojo_erc::token::erc721::ERC721::_worldContractMemberStateTrait; -use debug::PrintTrait; - -// -// Setup -// - -fn STATE() -> (IWorldDispatcher, ERC721::ContractState) { - let world = spawn_test_world( - array![ - erc_721_meta::TEST_CLASS_HASH, - erc_721_operator_approval::TEST_CLASS_HASH, - erc_721_owner::TEST_CLASS_HASH, - erc_721_balance::TEST_CLASS_HASH, - erc_721_token_approval::TEST_CLASS_HASH, - ] - ); - let mut state = ERC721::contract_state_for_testing(); - state._world.write(world.contract_address); - (world, state) -} - -fn setup() -> ERC721::ContractState { - let (world, mut state) = STATE(); - ERC721::constructor(ref state, world.contract_address, NAME, SYMBOL, URI, OWNER(), TOKEN_ID); - utils::drop_event(ZERO()); - state -} - -// fn setup_receiver() -> ContractAddress { -// utils::deploy(ERC721Receiver::TEST_CLASS_HASH, array![]) -// } - -// fn setup_camel_receiver() -> ContractAddress { -// utils::deploy(CamelERC721ReceiverMock::TEST_CLASS_HASH, array![]) -// } - -// fn setup_account() -> ContractAddress { -// let mut calldata = array![PUBKEY]; -// utils::deploy(Account::TEST_CLASS_HASH, calldata) -// } - -// fn setup_camel_account() -> ContractAddress { -// let mut calldata = array![PUBKEY]; -// utils::deploy(CamelAccountMock::TEST_CLASS_HASH, calldata) -// } - -// -// initializer & constructor -// - -#[test] -#[available_gas(20000000)] -fn test_constructor() { - let (world, mut state) = STATE(); - ERC721::constructor(ref state, world.contract_address, NAME, SYMBOL, URI, OWNER(), TOKEN_ID); - - assert(ERC721MetadataImpl::name(@state) == NAME, 'Name should be NAME'); - assert(ERC721MetadataImpl::symbol(@state) == SYMBOL, 'Symbol should be SYMBOL'); - assert(ERC721Impl::balance_of(@state, OWNER()) == 1, 'Balance should be one'); - assert(ERC721Impl::owner_of(@state, TOKEN_ID) == OWNER(), 'OWNER should be owner'); -// assert( -// SRC5Impl::supports_interface(@state, erc721::interface::IERC721_ID), 'Missing interface ID' -// ); -// assert( -// SRC5Impl::supports_interface(@state, erc721::interface::IERC721_METADATA_ID), -// 'missing interface ID' -// ); -// assert( -// SRC5Impl::supports_interface(@state, introspection::interface::ISRC5_ID), -// 'missing interface ID' -// ); -} - -#[test] -#[available_gas(10000000)] -fn test_initializer() { - let (world, mut state) = STATE(); - InternalImpl::initializer(ref state, NAME, SYMBOL, URI); - - assert(ERC721MetadataImpl::name(@state) == NAME, 'Name should be NAME'); - assert(ERC721MetadataImpl::symbol(@state) == SYMBOL, 'Symbol should be SYMBOL'); - - assert(ERC721Impl::balance_of(@state, OWNER()) == 0, 'Balance should be zero'); -// assert( -// SRC5Impl::supports_interface(@state, erc721::interface::IERC721_ID), 'Missing interface ID' -// ); -// assert( -// SRC5Impl::supports_interface(@state, erc721::interface::IERC721_METADATA_ID), -// 'missing interface ID' -// ); -// assert( -// SRC5Impl::supports_interface(@state, introspection::interface::ISRC5_ID), -// 'missing interface ID' -// ); -} - - -// -// Getters -// - -#[test] -#[available_gas(20000000)] -fn test_balance_of() { - let state = setup(); - assert(ERC721Impl::balance_of(@state, OWNER()) == 1, 'Should return balance'); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid account',))] -fn test_balance_of_zero() { - let state = setup(); - ERC721Impl::balance_of(@state, ZERO()); -} - -#[test] -#[available_gas(20000000)] -fn test_owner_of() { - let state = setup(); - assert(ERC721Impl::owner_of(@state, TOKEN_ID) == OWNER(), 'Should return owner'); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid token ID',))] -fn test_owner_of_non_minted() { - let state = setup(); - ERC721Impl::owner_of(@state, u256_from_felt252(7)); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid token ID',))] -fn test_token_uri_non_minted() { - let state = setup(); - ERC721MetadataImpl::token_uri(@state, u256_from_felt252(7)); -} - -#[test] -#[available_gas(20000000)] -fn test_get_approved() { - let mut state = setup(); - let spender = SPENDER(); - let token_id = TOKEN_ID; - - assert(ERC721Impl::get_approved(@state, token_id) == ZERO(), 'Should return non-approval'); - InternalImpl::_approve(ref state, spender, token_id); - assert(ERC721Impl::get_approved(@state, token_id) == spender, 'Should return approval'); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid token ID',))] -fn test_get_approved_nonexistent() { - let mut state = setup(); - ERC721Impl::get_approved(@state, u256_from_felt252(7)); -} - -#[test] -#[available_gas(20000000)] -fn test__exists() { - let (world, mut state) = STATE(); - let token_id = TOKEN_ID; - - assert(!InternalImpl::_exists(@state, token_id), 'Token should not exist'); - assert( - WorldInteractionsImpl::get_owner_of(@state, token_id).address == ZERO(), 'Invalid owner' - ); - - InternalImpl::_mint(ref state, RECIPIENT(), token_id); - - assert(InternalImpl::_exists(@state, token_id), 'Token should exist'); - assert( - WorldInteractionsImpl::get_owner_of(@state, token_id).address == RECIPIENT(), - 'Invalid owner' - ); - - InternalImpl::_burn(ref state, token_id); - - assert(!InternalImpl::_exists(@state, token_id), 'Token should not exist'); - assert( - WorldInteractionsImpl::get_owner_of(@state, token_id).address == ZERO(), 'Invalid owner' - ); -} - - -// -// approve & _approve -// - -#[test] -#[available_gas(20000000)] -fn test_approve_from_owner() { - let mut state = setup(); - - testing::set_caller_address(OWNER()); - ERC721Impl::approve(ref state, SPENDER(), TOKEN_ID); - assert_event_approval(OWNER(), SPENDER(), TOKEN_ID); - - assert( - ERC721Impl::get_approved(@state, TOKEN_ID) == SPENDER(), 'Spender not approved correctly' - ); -} - -#[test] -#[available_gas(20000000)] -fn test_approve_from_operator() { - let mut state = setup(); - - testing::set_caller_address(OWNER()); - ERC721Impl::set_approval_for_all(ref state, OPERATOR(), true); - utils::drop_event(ZERO()); - - testing::set_caller_address(OPERATOR()); - ERC721Impl::approve(ref state, SPENDER(), TOKEN_ID); - assert_event_approval(OWNER(), SPENDER(), TOKEN_ID); - - assert( - ERC721Impl::get_approved(@state, TOKEN_ID) == SPENDER(), 'Spender not approved correctly' - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: unauthorized caller',))] -fn test_approve_from_unauthorized() { - let mut state = setup(); - - testing::set_caller_address(OTHER()); - ERC721Impl::approve(ref state, SPENDER(), TOKEN_ID); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: approval to owner',))] -fn test_approve_to_owner() { - let mut state = setup(); - - testing::set_caller_address(OWNER()); - ERC721Impl::approve(ref state, OWNER(), TOKEN_ID); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid token ID',))] -fn test_approve_nonexistent() { - // let mut state = STATE(); - let (world, mut state) = STATE(); - ERC721Impl::approve(ref state, SPENDER(), TOKEN_ID); -} - -#[test] -#[available_gas(20000000)] -fn test__approve() { - let mut state = setup(); - InternalImpl::_approve(ref state, SPENDER(), TOKEN_ID); - assert_event_approval(OWNER(), SPENDER(), TOKEN_ID); - - assert( - ERC721Impl::get_approved(@state, TOKEN_ID) == SPENDER(), 'Spender not approved correctly' - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: approval to owner',))] -fn test__approve_to_owner() { - let mut state = setup(); - InternalImpl::_approve(ref state, OWNER(), TOKEN_ID); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid token ID',))] -fn test__approve_nonexistent() { - //let mut state = STATE(); - let (world, mut state) = STATE(); - InternalImpl::_approve(ref state, SPENDER(), TOKEN_ID); -} - -// -// set_approval_for_all & _set_approval_for_all -// - -#[test] -#[available_gas(20000000)] -fn test_set_approval_for_all() { - //let mut state = STATE(); - let (world, mut state) = STATE(); - testing::set_caller_address(OWNER()); - - assert(!ERC721Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), 'Invalid default value'); - - ERC721Impl::set_approval_for_all(ref state, OPERATOR(), true); - assert_event_approval_for_all(OWNER(), OPERATOR(), true); - - assert( - ERC721Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), - 'Operator not approved correctly' - ); - - ERC721Impl::set_approval_for_all(ref state, OPERATOR(), false); - assert_event_approval_for_all(OWNER(), OPERATOR(), false); - - assert( - !ERC721Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), - 'Approval not revoked correctly' - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: self approval',))] -fn test_set_approval_for_all_owner_equal_operator_true() { - //let mut state = STATE(); - let (world, mut state) = STATE(); - testing::set_caller_address(OWNER()); - ERC721Impl::set_approval_for_all(ref state, OWNER(), true); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: self approval',))] -fn test_set_approval_for_all_owner_equal_operator_false() { - //let mut state = STATE(); - let (world, mut state) = STATE(); - testing::set_caller_address(OWNER()); - ERC721Impl::set_approval_for_all(ref state, OWNER(), false); -} - -#[test] -#[available_gas(20000000)] -fn test__set_approval_for_all() { - //let mut state = STATE(); - let (world, mut state) = STATE(); - assert(!ERC721Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), 'Invalid default value'); - - InternalImpl::_set_approval_for_all(ref state, OWNER(), OPERATOR(), true); - assert_event_approval_for_all(OWNER(), OPERATOR(), true); - - assert( - ERC721Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), - 'Operator not approved correctly' - ); - - InternalImpl::_set_approval_for_all(ref state, OWNER(), OPERATOR(), false); - assert_event_approval_for_all(OWNER(), OPERATOR(), false); - - assert( - !ERC721Impl::is_approved_for_all(@state, OWNER(), OPERATOR()), - 'Operator not approved correctly' - ); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: self approval',))] -fn test__set_approval_for_all_owner_equal_operator_true() { - //let mut state = STATE(); - let (world, mut state) = STATE(); - InternalImpl::_set_approval_for_all(ref state, OWNER(), OWNER(), true); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: self approval',))] -fn test__set_approval_for_all_owner_equal_operator_false() { - // let mut state = STATE(); - let (world, mut state) = STATE(); - InternalImpl::_set_approval_for_all(ref state, OWNER(), OWNER(), false); -} - - -// -// transfer_from & transferFrom -// - -#[test] -#[available_gas(60000000)] -fn test_transfer_from_owner() { - let mut state = setup(); - let token_id = TOKEN_ID; - let owner = OWNER(); - let recipient = RECIPIENT(); - // set approval to check reset - InternalImpl::_approve(ref state, OTHER(), token_id); - utils::drop_event(ZERO()); - - assert_state_before_transfer(@state, owner, recipient, token_id); - assert(ERC721Impl::get_approved(@state, token_id) == OTHER(), 'Approval not implicitly reset'); - - testing::set_caller_address(owner); - ERC721Impl::transfer_from(ref state, owner, recipient, token_id); - assert_event_transfer(owner, recipient, token_id); - - assert_state_after_transfer(@state, owner, recipient, token_id); -} - -#[test] -#[available_gas(50000000)] -fn test_transferFrom_owner() { - let mut state = setup(); - let token_id = TOKEN_ID; - let owner = OWNER(); - let recipient = RECIPIENT(); - // set approval to check reset - InternalImpl::_approve(ref state, OTHER(), token_id); - utils::drop_event(ZERO()); - - assert_state_before_transfer(@state, owner, recipient, token_id); - assert(ERC721Impl::get_approved(@state, token_id) == OTHER(), 'Approval not implicitly reset'); - - testing::set_caller_address(owner); - ERC721CamelOnlyImpl::transferFrom(ref state, owner, recipient, token_id); - assert_event_transfer(owner, recipient, token_id); - - assert_state_after_transfer(@state, owner, recipient, token_id); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid token ID',))] -fn test_transfer_from_nonexistent() { - //let mut state = STATE(); - let (world, mut state) = STATE(); - ERC721Impl::transfer_from(ref state, ZERO(), RECIPIENT(), TOKEN_ID); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid token ID',))] -fn test_transferFrom_nonexistent() { - //let mut state = STATE(); - let (world, mut state) = STATE(); - ERC721CamelOnlyImpl::transferFrom(ref state, ZERO(), RECIPIENT(), TOKEN_ID); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid receiver',))] -fn test_transfer_from_to_zero() { - let mut state = setup(); - testing::set_caller_address(OWNER()); - ERC721Impl::transfer_from(ref state, OWNER(), ZERO(), TOKEN_ID); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid receiver',))] -fn test_transferFrom_to_zero() { - let mut state = setup(); - - testing::set_caller_address(OWNER()); - ERC721CamelOnlyImpl::transferFrom(ref state, OWNER(), ZERO(), TOKEN_ID); -} - -#[test] -#[available_gas(50000000)] -fn test_transfer_from_to_owner() { - let mut state = setup(); - - assert(ERC721Impl::owner_of(@state, TOKEN_ID) == OWNER(), 'Ownership before'); - assert(ERC721Impl::balance_of(@state, OWNER()) == 1, 'Balance of owner before'); - - testing::set_caller_address(OWNER()); - ERC721Impl::transfer_from(ref state, OWNER(), OWNER(), TOKEN_ID); - assert_event_transfer(OWNER(), OWNER(), TOKEN_ID); - - assert(ERC721Impl::owner_of(@state, TOKEN_ID) == OWNER(), 'Ownership after'); - assert(ERC721Impl::balance_of(@state, OWNER()) == 1, 'Balance of owner after'); -} - -#[test] -#[available_gas(50000000)] -fn test_transferFrom_to_owner() { - let mut state = setup(); - - assert(ERC721Impl::owner_of(@state, TOKEN_ID) == OWNER(), 'Ownership before'); - assert(ERC721Impl::balance_of(@state, OWNER()) == 1, 'Balance of owner before'); - - testing::set_caller_address(OWNER()); - ERC721CamelOnlyImpl::transferFrom(ref state, OWNER(), OWNER(), TOKEN_ID); - assert_event_transfer( OWNER(), OWNER(), TOKEN_ID); - - assert(ERC721Impl::owner_of(@state, TOKEN_ID) == OWNER(), 'Ownership after'); - assert(ERC721Impl::balance_of(@state, OWNER()) == 1, 'Balance of owner after'); -} - -#[test] -#[available_gas(50000000)] -fn test_transfer_from_approved() { - let mut state = setup(); - let token_id = TOKEN_ID; - let owner = OWNER(); - let recipient = RECIPIENT(); - assert_state_before_transfer(@state, owner, recipient, token_id); - - testing::set_caller_address(owner); - ERC721Impl::approve(ref state, OPERATOR(), token_id); - utils::drop_event(ZERO()); - - testing::set_caller_address(OPERATOR()); - ERC721Impl::transfer_from(ref state, owner, recipient, token_id); - assert_event_transfer(owner, recipient, token_id); - - assert_state_after_transfer(@state, owner, recipient, token_id); -} - -#[test] -#[available_gas(50000000)] -fn test_transferFrom_approved() { - let mut state = setup(); - let token_id = TOKEN_ID; - let owner = OWNER(); - let recipient = RECIPIENT(); - assert_state_before_transfer(@state,owner, recipient, token_id); - - testing::set_caller_address(owner); - ERC721Impl::approve(ref state, OPERATOR(), token_id); - utils::drop_event(ZERO()); - - testing::set_caller_address(OPERATOR()); - ERC721CamelOnlyImpl::transferFrom(ref state, owner, recipient, token_id); - assert_event_transfer(owner, recipient, token_id); - - assert_state_after_transfer(@state,owner, recipient, token_id); -} - -#[test] -#[available_gas(50000000)] -fn test_transfer_from_approved_for_all() { - let mut state = setup(); - let token_id = TOKEN_ID; - let owner = OWNER(); - let recipient = RECIPIENT(); - - assert_state_before_transfer(@state, owner, recipient, token_id); - - testing::set_caller_address(owner); - ERC721Impl::set_approval_for_all(ref state, OPERATOR(), true); - utils::drop_event(ZERO()); - - testing::set_caller_address(OPERATOR()); - ERC721Impl::transfer_from(ref state, owner, recipient, token_id); - assert_event_transfer(owner, recipient, token_id); - - assert_state_after_transfer(@state, owner, recipient, token_id); -} - -#[test] -#[available_gas(50000000)] -fn test_transferFrom_approved_for_all() { - let mut state = setup(); - let token_id = TOKEN_ID; - let owner = OWNER(); - let recipient = RECIPIENT(); - - assert_state_before_transfer(@state,owner, recipient, token_id); - - testing::set_caller_address(owner); - ERC721Impl::set_approval_for_all(ref state, OPERATOR(), true); - utils::drop_event(ZERO()); - - testing::set_caller_address(OPERATOR()); - ERC721CamelOnlyImpl::transferFrom(ref state, owner, recipient, token_id); - assert_event_transfer(owner, recipient, token_id); - - assert_state_after_transfer(@state,owner, recipient, token_id); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: unauthorized caller',))] -fn test_transfer_from_unauthorized() { - let mut state = setup(); - testing::set_caller_address(OTHER()); - ERC721Impl::transfer_from(ref state, OWNER(), RECIPIENT(), TOKEN_ID); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: unauthorized caller',))] -fn test_transferFrom_unauthorized() { - let mut state = setup(); - testing::set_caller_address(OTHER()); - ERC721CamelOnlyImpl::transferFrom(ref state, OWNER(), RECIPIENT(), TOKEN_ID); -} - -// // -// // safe_transfer_from & safeTransferFrom -// // - -// #[test] -// #[available_gas(20000000)] -// fn test_safe_transfer_from_to_account() { -// let mut state = setup(); -// let account = setup_account(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, account, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::safe_transfer_from(ref state, owner, account, token_id, DATA(true)); -// assert_event_transfer(owner, account, token_id); - -// assert_state_after_transfer(@state,owner, account, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safeTransferFrom_to_account() { -// let mut state = setup(); -// let account = setup_account(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, account, token_id); - -// testing::set_caller_address(owner); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, account, token_id, DATA(true)); -// assert_event_transfer(owner, account, token_id); - -// assert_state_after_transfer(@state,owner, account, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safe_transfer_from_to_account_camel() { -// let mut state = setup(); -// let account = setup_camel_account(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, account, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::safe_transfer_from(ref state, owner, account, token_id, DATA(true)); -// assert_event_transfer(owner, account, token_id); - -// assert_state_after_transfer(@state,owner, account, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safeTransferFrom_to_account_camel() { -// let mut state = setup(); -// let account = setup_camel_account(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, account, token_id); - -// testing::set_caller_address(owner); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, account, token_id, DATA(true)); -// assert_event_transfer(owner, account, token_id); - -// assert_state_after_transfer(@state,owner, account, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safe_transfer_from_to_receiver() { -// let mut state = setup(); -// let receiver = setup_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::safe_transfer_from(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safeTransferFrom_to_receiver() { -// let mut state = setup(); -// let receiver = setup_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safe_transfer_from_to_receiver_camel() { -// let mut state = setup(); -// let receiver = setup_camel_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::safe_transfer_from(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safeTransferFrom_to_receiver_camel() { -// let mut state = setup(); -// let receiver = setup_camel_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: safe transfer failed',))] -// fn test_safe_transfer_from_to_receiver_failure() { -// let mut state = setup(); -// let receiver = setup_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// testing::set_caller_address(owner); -// ERC721Impl::safe_transfer_from(ref state, owner, receiver, token_id, DATA(false)); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: safe transfer failed',))] -// fn test_safeTransferFrom_to_receiver_failure() { -// let mut state = setup(); -// let receiver = setup_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// testing::set_caller_address(owner); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, receiver, token_id, DATA(false)); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: safe transfer failed',))] -// fn test_safe_transfer_from_to_receiver_failure_camel() { -// let mut state = setup(); -// let receiver = setup_camel_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// testing::set_caller_address(owner); -// ERC721Impl::safe_transfer_from(ref state, owner, receiver, token_id, DATA(false)); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: safe transfer failed',))] -// fn test_safeTransferFrom_to_receiver_failure_camel() { -// let mut state = setup(); -// let receiver = setup_camel_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// testing::set_caller_address(owner); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, receiver, token_id, DATA(false)); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -// fn test_safe_transfer_from_to_non_receiver() { -// let mut state = setup(); -// let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// testing::set_caller_address(owner); -// ERC721Impl::safe_transfer_from(ref state, owner, recipient, token_id, DATA(true)); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -// fn test_safeTransferFrom_to_non_receiver() { -// let mut state = setup(); -// let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// testing::set_caller_address(owner); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, recipient, token_id, DATA(true)); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: invalid token ID',))] -// fn test_safe_transfer_from_nonexistent() { -// let mut state = STATE(); -// ERC721Impl::safe_transfer_from(ref state, ZERO(), RECIPIENT(), TOKEN_ID, DATA(true)); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: invalid token ID',))] -// fn test_safeTransferFrom_nonexistent() { -// let mut state = STATE(); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, ZERO(), RECIPIENT(), TOKEN_ID, DATA(true)); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: invalid receiver',))] -// fn test_safe_transfer_from_to_zero() { -// let mut state = setup(); -// testing::set_caller_address(OWNER()); -// ERC721Impl::safe_transfer_from(ref state, OWNER(), ZERO(), TOKEN_ID, DATA(true)); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: invalid receiver',))] -// fn test_safeTransferFrom_to_zero() { -// let mut state = setup(); -// testing::set_caller_address(OWNER()); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, OWNER(), ZERO(), TOKEN_ID, DATA(true)); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safe_transfer_from_to_owner() { -// let mut state = STATE(); -// let token_id = TOKEN_ID; -// let owner = setup_receiver(); -// InternalImpl::initializer(ref state, NAME, SYMBOL); -// InternalImpl::_mint(ref state, owner, token_id); -// utils::drop_event(ZERO()); - -// assert(ERC721Impl::owner_of(@state, token_id) == owner, 'Ownership before'); -// assert(ERC721Impl::balance_of(@state, owner) == 1, 'Balance of owner before'); - -// testing::set_caller_address(owner); -// ERC721Impl::safe_transfer_from(ref state, owner, owner, token_id, DATA(true)); -// assert_event_transfer(owner, owner, token_id); - -// assert(ERC721Impl::owner_of(@state, token_id) == owner, 'Ownership after'); -// assert(ERC721Impl::balance_of(@state, owner) == 1, 'Balance of owner after'); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safeTransferFrom_to_owner() { -// let mut state = STATE(); -// let token_id = TOKEN_ID; -// let owner = setup_receiver(); -// InternalImpl::initializer(ref state, NAME, SYMBOL); -// InternalImpl::_mint(ref state, owner, token_id); -// utils::drop_event(ZERO()); - -// assert(ERC721Impl::owner_of(@state, token_id) == owner, 'Ownership before'); -// assert(ERC721Impl::balance_of(@state, owner) == 1, 'Balance of owner before'); - -// testing::set_caller_address(owner); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, owner, token_id, DATA(true)); -// assert_event_transfer(owner, owner, token_id); - -// assert(ERC721Impl::owner_of(@state, token_id) == owner, 'Ownership after'); -// assert(ERC721Impl::balance_of(@state, owner) == 1, 'Balance of owner after'); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safe_transfer_from_to_owner_camel() { -// let mut state = STATE(); -// let token_id = TOKEN_ID; -// let owner = setup_camel_receiver(); -// InternalImpl::initializer(ref state, NAME, SYMBOL); -// InternalImpl::_mint(ref state, owner, token_id); -// utils::drop_event(ZERO()); - -// assert(ERC721Impl::owner_of(@state, token_id) == owner, 'Ownership before'); -// assert(ERC721Impl::balance_of(@state, owner) == 1, 'Balance of owner before'); - -// testing::set_caller_address(owner); -// ERC721Impl::safe_transfer_from(ref state, owner, owner, token_id, DATA(true)); -// assert_event_transfer(owner, owner, token_id); - -// assert(ERC721Impl::owner_of(@state, token_id) == owner, 'Ownership after'); -// assert(ERC721Impl::balance_of(@state, owner) == 1, 'Balance of owner after'); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safeTransferFrom_to_owner_camel() { -// let mut state = STATE(); -// let token_id = TOKEN_ID; -// let owner = setup_camel_receiver(); -// InternalImpl::initializer(ref state, NAME, SYMBOL); -// InternalImpl::_mint(ref state, owner, token_id); -// utils::drop_event(ZERO()); - -// assert(ERC721Impl::owner_of(@state, token_id) == owner, 'Ownership before'); -// assert(ERC721Impl::balance_of(@state, owner) == 1, 'Balance of owner before'); - -// testing::set_caller_address(owner); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, owner, token_id, DATA(true)); -// assert_event_transfer(owner, owner, token_id); - -// assert(ERC721Impl::owner_of(@state, token_id) == owner, 'Ownership after'); -// assert(ERC721Impl::balance_of(@state, owner) == 1, 'Balance of owner after'); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safe_transfer_from_approved() { -// let mut state = setup(); -// let receiver = setup_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::approve(ref state, OPERATOR(), token_id); -// utils::drop_event(ZERO()); - -// testing::set_caller_address(OPERATOR()); -// ERC721Impl::safe_transfer_from(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safeTransferFrom_approved() { -// let mut state = setup(); -// let receiver = setup_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::approve(ref state, OPERATOR(), token_id); -// utils::drop_event(ZERO()); - -// testing::set_caller_address(OPERATOR()); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safe_transfer_from_approved_camel() { -// let mut state = setup(); -// let receiver = setup_camel_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::approve(ref state, OPERATOR(), token_id); -// utils::drop_event(ZERO()); - -// testing::set_caller_address(OPERATOR()); -// ERC721Impl::safe_transfer_from(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safeTransferFrom_approved_camel() { -// let mut state = setup(); -// let receiver = setup_camel_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::approve(ref state, OPERATOR(), token_id); -// utils::drop_event(ZERO()); - -// testing::set_caller_address(OPERATOR()); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safe_transfer_from_approved_for_all() { -// let mut state = setup(); -// let receiver = setup_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::set_approval_for_all(ref state, OPERATOR(), true); -// utils::drop_event(ZERO()); - -// testing::set_caller_address(OPERATOR()); -// ERC721Impl::safe_transfer_from(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safeTransferFrom_approved_for_all() { -// let mut state = setup(); -// let receiver = setup_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::set_approval_for_all(ref state, OPERATOR(), true); -// utils::drop_event(ZERO()); - -// testing::set_caller_address(OPERATOR()); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safe_transfer_from_approved_for_all_camel() { -// let mut state = setup(); -// let receiver = setup_camel_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::set_approval_for_all(ref state, OPERATOR(), true); -// utils::drop_event(ZERO()); - -// testing::set_caller_address(OPERATOR()); -// ERC721Impl::safe_transfer_from(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test_safeTransferFrom_approved_for_all_camel() { -// let mut state = setup(); -// let receiver = setup_camel_receiver(); -// let token_id = TOKEN_ID; -// let owner = OWNER(); - -// assert_state_before_transfer(@state,owner, receiver, token_id); - -// testing::set_caller_address(owner); -// ERC721Impl::set_approval_for_all(ref state, OPERATOR(), true); -// utils::drop_event(ZERO()); - -// testing::set_caller_address(OPERATOR()); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, owner, receiver, token_id, DATA(true)); -// assert_event_transfer(owner, receiver, token_id); - -// assert_state_after_transfer(@state,owner, receiver, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: unauthorized caller',))] -// fn test_safe_transfer_from_unauthorized() { -// let mut state = setup(); -// testing::set_caller_address(OTHER()); -// ERC721Impl::safe_transfer_from(ref state, OWNER(), RECIPIENT(), TOKEN_ID, DATA(true)); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: unauthorized caller',))] -// fn test_safeTransferFrom_unauthorized() { -// let mut state = setup(); -// testing::set_caller_address(OTHER()); -// ERC721CamelOnlyImpl::safeTransferFrom(ref state, OWNER(), RECIPIENT(), TOKEN_ID, DATA(true)); -// } - -// -// _transfer -// - -#[test] -#[available_gas(50000000)] -fn test__transfer() { - let mut state = setup(); - let token_id = TOKEN_ID; - let owner = OWNER(); - let recipient = RECIPIENT(); - - assert_state_before_transfer(@state, owner, recipient, token_id); - - InternalImpl::_transfer(ref state, owner, recipient, token_id); - assert_event_transfer(owner, recipient, token_id); - - assert_state_after_transfer(@state, owner, recipient, token_id); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid token ID',))] -fn test__transfer_nonexistent() { - let (world, mut state) = STATE(); - InternalImpl::_transfer(ref state, ZERO(), RECIPIENT(), TOKEN_ID); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid receiver',))] -fn test__transfer_to_zero() { - let mut state = setup(); - InternalImpl::_transfer(ref state, OWNER(), ZERO(), TOKEN_ID); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: wrong sender',))] -fn test__transfer_from_invalid_owner() { - let mut state = setup(); - InternalImpl::_transfer(ref state, RECIPIENT(), OWNER(), TOKEN_ID); -} - -// -// _mint -// - -#[test] -#[available_gas(20000000)] -fn test__mint() { - let (world, mut state) = STATE(); - let recipient = RECIPIENT(); - let token_id = TOKEN_ID; - - assert_state_before_mint(@state, recipient); - InternalImpl::_mint(ref state, recipient, TOKEN_ID); - assert_event_transfer(ZERO(), recipient, token_id); - - assert_state_after_mint(@state, recipient, token_id); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: invalid receiver',))] -fn test__mint_to_zero() { - let (world, mut state) = STATE(); - InternalImpl::_mint(ref state, ZERO(), TOKEN_ID); -} - -#[test] -#[available_gas(20000000)] -#[should_panic(expected: ('ERC721: token already minted',))] -fn test__mint_already_exist() { - let mut state = setup(); - InternalImpl::_mint(ref state, RECIPIENT(), TOKEN_ID); -} - -// // -// // _safe_mint -// // - -// #[test] -// #[available_gas(20000000)] -// fn test__safe_mint_to_receiver() { -// let mut state = STATE(); -// let recipient = setup_receiver(); -// let token_id = TOKEN_ID; - -// assert_state_before_mint(@state,recipient); -// InternalImpl::_safe_mint(ref state, recipient, token_id, DATA(true)); -// assert_event_transfer(ZERO(), recipient, token_id); - -// assert_state_after_mint(@state,recipient, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test__safe_mint_to_receiver_camel() { -// let mut state = STATE(); -// let recipient = setup_camel_receiver(); -// let token_id = TOKEN_ID; - -// assert_state_before_mint(@state,recipient); -// InternalImpl::_safe_mint(ref state, recipient, token_id, DATA(true)); -// assert_event_transfer(ZERO(), recipient, token_id); - -// assert_state_after_mint(@state,recipient, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test__safe_mint_to_account() { -// let mut state = STATE(); -// let account = setup_account(); -// let token_id = TOKEN_ID; - -// assert_state_before_mint(@state,account); -// InternalImpl::_safe_mint(ref state, account, token_id, DATA(true)); -// assert_event_transfer(ZERO(), account, token_id); - -// assert_state_after_mint(@state,account, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// fn test__safe_mint_to_account_camel() { -// let mut state = STATE(); -// let account = setup_camel_account(); -// let token_id = TOKEN_ID; - -// assert_state_before_mint(@state,account); -// InternalImpl::_safe_mint(ref state, account, token_id, DATA(true)); -// assert_event_transfer(ZERO(), account, token_id); - -// assert_state_after_mint(@state,account, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -// fn test__safe_mint_to_non_receiver() { -// let mut state = STATE(); -// let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); -// let token_id = TOKEN_ID; - -// assert_state_before_mint(@state,recipient); -// InternalImpl::_safe_mint(ref state, recipient, token_id, DATA(true)); -// assert_state_after_mint(@state,recipient, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: safe mint failed',))] -// fn test__safe_mint_to_receiver_failure() { -// let mut state = STATE(); -// let recipient = setup_receiver(); -// let token_id = TOKEN_ID; - -// assert_state_before_mint(@state,recipient); -// InternalImpl::_safe_mint(ref state, recipient, token_id, DATA(false)); -// assert_state_after_mint(@state,recipient, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: safe mint failed',))] -// fn test__safe_mint_to_receiver_failure_camel() { -// let mut state = STATE(); -// let recipient = setup_camel_receiver(); -// let token_id = TOKEN_ID; - -// assert_state_before_mint(@state,recipient); -// InternalImpl::_safe_mint(ref state, recipient, token_id, DATA(false)); -// assert_state_after_mint(@state,recipient, token_id); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: invalid receiver',))] -// fn test__safe_mint_to_zero() { -// let mut state = STATE(); -// InternalImpl::_safe_mint(ref state, ZERO(), TOKEN_ID, DATA(true)); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: token already minted',))] -// fn test__safe_mint_already_exist() { -// let mut state = setup(); -// InternalImpl::_safe_mint(ref state, RECIPIENT(), TOKEN_ID, DATA(true)); -// } - -// -// _burn -// - -#[test] -#[available_gas(25000000)] -fn test__burn() { - let mut state = setup(); - - InternalImpl::_approve(ref state, OTHER(), TOKEN_ID); - utils::drop_event(ZERO()); - - assert(ERC721Impl::owner_of(@state, TOKEN_ID) == OWNER(), 'Ownership before'); - assert(ERC721Impl::balance_of(@state, OWNER()) == 1, 'Balance of owner before'); - assert(ERC721Impl::get_approved(@state, TOKEN_ID) == OTHER(), 'Approval before'); - - InternalImpl::_burn(ref state, TOKEN_ID); - assert_event_transfer(OWNER(), ZERO(), TOKEN_ID); - - assert( - WorldInteractionsImpl::get_owner_of(@state, TOKEN_ID).address == ZERO(), 'Ownership after' - ); - assert(ERC721Impl::balance_of(@state, OWNER()) == 0, 'Balance of owner after'); - assert( - WorldInteractionsImpl::get_token_approval(@state, TOKEN_ID).address == ZERO(), - 'Approval after' - ); -} - -#[test] -#[available_gas(30000000)] -#[should_panic(expected: ('ERC721: invalid token ID',))] -fn test__burn_nonexistent() { - let (mut world, mut state) = STATE(); - InternalImpl::_burn(ref state, TOKEN_ID); -} - -// -// _set_token_uri -// - -// #[test] -// #[available_gas(20000000)] -// fn test__set_token_uri() { -// let mut state = setup(); - -// assert(ERC721MetadataImpl::token_uri(@state, TOKEN_ID) == 0, 'URI should be 0'); -// InternalImpl::_set_token_uri(ref state, TOKEN_ID, URI); -// assert(ERC721MetadataImpl::token_uri(@state, TOKEN_ID) == URI, 'URI should be set'); -// } - -// #[test] -// #[available_gas(20000000)] -// #[should_panic(expected: ('ERC721: invalid token ID',))] -// fn test__set_token_uri_nonexistent() { -// let mut state = STATE(); -// InternalImpl::_set_token_uri(ref state, TOKEN_ID, URI); -// } - -// -// Helpers -// - -fn assert_state_before_transfer( - state: @ERC721::ContractState, - owner: ContractAddress, - recipient: ContractAddress, - token_id: u256 -) { - assert(ERC721Impl::owner_of(state, token_id) == owner, 'Ownership before'); - assert(ERC721Impl::balance_of(state, owner) == 1, 'Balance of owner before'); - assert(ERC721Impl::balance_of(state, recipient) == 0, 'Balance of recipient before'); -} - -fn assert_state_after_transfer( - state: @ERC721::ContractState, - owner: ContractAddress, - recipient: ContractAddress, - token_id: u256 -) { - assert(ERC721Impl::owner_of(state, token_id) == recipient, 'Ownership after'); - assert(ERC721Impl::balance_of(state, owner) == 0, 'Balance of owner after'); - assert(ERC721Impl::balance_of(state, recipient) == 1, 'Balance of recipient after'); - assert(ERC721Impl::get_approved(state, token_id) == ZERO(), 'Approval not implicitly reset'); -} - -fn assert_state_before_mint(state: @ERC721::ContractState, recipient: ContractAddress) { - assert(ERC721Impl::balance_of(state, recipient) == 0, 'Balance of recipient before'); -} - -fn assert_state_after_mint( - state: @ERC721::ContractState, recipient: ContractAddress, token_id: u256 -) { - assert(ERC721Impl::owner_of(state, token_id) == recipient, 'Ownership after'); - assert(ERC721Impl::balance_of(state, recipient) == 1, 'Balance of recipient after'); - assert(ERC721Impl::get_approved(state, token_id) == ZERO(), 'Approval implicitly set'); -} - -fn assert_event_approval_for_all( - owner: ContractAddress, operator: ContractAddress, approved: bool -) { - let event = utils::pop_log::(ZERO()).unwrap(); - assert(event.owner == owner, 'Invalid `owner`'); - assert(event.operator == operator, 'Invalid `operator`'); - assert(event.approved == approved, 'Invalid `approved`'); - utils::assert_no_events_left(ZERO()); -} - -fn assert_event_approval(owner: ContractAddress, approved: ContractAddress, token_id: u256) { - let event = utils::pop_log::(ZERO()).unwrap(); - assert(event.owner == owner, 'Invalid `owner`'); - assert(event.approved == approved, 'Invalid `approved`'); - assert(event.token_id == token_id, 'Invalid `token_id`'); - utils::assert_no_events_left(ZERO()); -} - -fn assert_event_transfer(from: ContractAddress, to: ContractAddress, token_id: u256) { - let event = utils::pop_log::(ZERO()).unwrap(); - assert(event.from == from, 'Invalid `from`'); - assert(event.to == to, 'Invalid `to`'); - assert(event.token_id == token_id, 'Invalid `token_id`'); - utils::assert_no_events_left(ZERO()); -} diff --git a/crates/dojo-erc/src/tests/test_erc1155.cairo b/crates/dojo-erc/src/tests/test_erc1155.cairo deleted file mode 100644 index 5ce73b8230..0000000000 --- a/crates/dojo-erc/src/tests/test_erc1155.cairo +++ /dev/null @@ -1,629 +0,0 @@ -use zeroable::Zeroable; -use traits::{Into, Default, IndexView}; -use option::OptionTrait; -use array::ArrayTrait; -use serde::Serde; -use starknet::ContractAddress; -use starknet::testing::set_contract_address; - -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - -use dojo_erc::tests::test_utils::impersonate; -use dojo_erc::tests::test_erc1155_utils::{ - spawn_world, deploy_erc1155, deploy_default, deploy_testcase1, ZERO, USER1, USER2, DEPLOYER, - PROXY -}; - -use dojo_erc::erc165::interface::IERC165_ID; -use dojo_erc::erc1155::interface::{ - IERC1155A, IERC1155ADispatcher, IERC1155ADispatcherTrait, IERC1155_ID, IERC1155_METADATA_ID, - IERC1155_RECEIVER_ID -}; - -use dojo_erc::erc1155::erc1155::ERC1155::{Event, TransferSingle, TransferBatch, ApprovalForAll}; - - -#[test] -#[available_gas(30000000)] -fn test_deploy() { - let world = spawn_world(DEPLOYER()); - let erc1155_address = deploy_erc1155(world, DEPLOYER(), 'uri', 'seed-42'); - let erc1155 = IERC1155ADispatcher { contract_address: erc1155_address }; - assert(erc1155.owner() == DEPLOYER(), 'invalid owner'); -} - -#[test] -#[available_gas(30000000)] -fn test_deploy_default() { - let (world, erc1155) = deploy_default(); - assert(erc1155.owner() == DEPLOYER(), 'invalid owner'); -} - - -// -// supports_interface -// - -#[test] -#[available_gas(30000000)] -fn test_should_support_interfaces() { - let (world, erc1155) = deploy_default(); - - assert(erc1155.supports_interface(IERC165_ID) == true, 'should support erc165'); - assert(erc1155.supports_interface(IERC1155_ID) == true, 'should support erc1155'); - assert( - erc1155.supports_interface(IERC1155_METADATA_ID) == true, 'should support erc1155_metadata' - ); -} - -// -// uri -// - -#[test] -#[available_gas(30000000)] -fn test_uri() { - let (world, erc1155) = deploy_default(); - assert(erc1155.uri(64) == 'uri', 'invalid uri'); -} - - -// -// behaves like an ERC1155 -// - -// -// balance_of -// -#[test] -#[available_gas(30000000)] -#[should_panic(expected: ('ERC1155: invalid owner address', 'ENTRYPOINT_FAILED',))] -fn test_balance_of_zero_address() { - //reverts when queried about the zero address - - let (world, erc1155) = deploy_default(); - erc1155.balance_of(ZERO(), 0); // should panic -} - -#[test] -#[available_gas(30000000)] -fn test_balance_of_empty_balance() { - // when accounts don't own tokens - // returns zero for given addresses - let (world, erc1155) = deploy_default(); - assert(erc1155.balance_of(USER1(), 0) == 0, 'should be 0'); - assert(erc1155.balance_of(USER1(), 69) == 0, 'should be 0'); - assert(erc1155.balance_of(USER2(), 0) == 0, 'should be 0'); -} - -#[test] -#[available_gas(30000000)] -fn test_balance_with_tokens() { - // when accounts own some tokens - // returns the amount of tokens owned by the given addresses - let (world, erc1155) = deploy_default(); - - erc1155.mint(USER1(), 0, 1, array![]); - erc1155.mint(USER1(), 69, 42, array![]); - erc1155.mint(USER2(), 69, 5, array![]); - - assert(erc1155.balance_of(USER1(), 0) == 1, 'should be 1'); - assert(erc1155.balance_of(USER1(), 69) == 42, 'should be 42'); - assert(erc1155.balance_of(USER2(), 69) == 5, 'should be 5'); -} - -// -// balance_of_batch -// - -#[test] -#[available_gas(30000000)] -#[should_panic(expected: ('ERC1155: invalid length', 'ENTRYPOINT_FAILED',))] -fn test_balance_of_batch_with_invalid_input() { - // reverts when input arrays don't match up - let (world, erc1155) = deploy_default(); - erc1155.balance_of_batch(array![USER1(), USER2()], array![0]); - erc1155.balance_of_batch(array![USER1()], array![0, 1, 2]); -} - -#[test] -#[available_gas(30000000)] -#[should_panic(expected: ('ERC1155: invalid owner address', 'ENTRYPOINT_FAILED',))] -fn test_balance_of_batch_address_zero() { - // reverts when input arrays don't match up - let (world, erc1155) = deploy_default(); - erc1155.balance_of_batch(array![USER1(), ZERO()], array![0, 1]); -} - -#[test] -#[available_gas(30000000)] -fn test_balance_of_batch_empty_account() { - // when accounts don't own tokens - // returns zeros for each account - let (world, erc1155) = deploy_default(); - let balances = erc1155.balance_of_batch(array![USER1(), USER1(), USER1()], array![0, 1, 5]); - let bals = @balances; - assert(balances.len() == 3, 'should be 3'); - assert(bals[0] == @0_u256, 'should be 0'); - assert(bals[1] == @0_u256, 'should be 0'); - assert(bals[2] == @0_u256, 'should be 0'); -} - -#[test] -#[available_gas(30000000)] -fn test_balance_of_batch_with_tokens() { - // when accounts own some tokens - // returns amounts owned by each account in order passed - let (world, erc1155) = deploy_default(); - - erc1155.mint(USER1(), 0, 1, array![]); - erc1155.mint(USER1(), 69, 42, array![]); - erc1155.mint(USER2(), 69, 2, array![]); - - let balances = erc1155.balance_of_batch(array![USER1(), USER1(), USER2()], array![0, 69, 69]); - let bals = @balances; - assert(balances.len() == 3, 'should be 3'); - assert(bals[0] == @1_u256, 'should be 1'); - assert(bals[1] == @42_u256, 'should be 42'); - assert(bals[2] == @2_u256, 'should be 2'); -} - -#[test] -#[available_gas(30000000)] -fn test_balance_of_batch_with_tokens_2() { - // when accounts own some tokens - // returns multiple times the balance of the same address when asked - let (world, erc1155) = deploy_default(); - - erc1155.mint(USER1(), 0, 1, array![]); - erc1155.mint(USER2(), 69, 2, array![]); - - let balances = erc1155.balance_of_batch(array![USER1(), USER2(), USER1()], array![0, 69, 0]); - let bals = @balances; - assert(balances.len() == 3, 'should be 3'); - assert(bals[0] == @1_u256, 'should be 1'); - assert(bals[1] == @2_u256, 'should be 2'); - assert(bals[2] == @1_u256, 'should be 1'); -} - - -// -// balance_of_batch -// - -#[test] -#[available_gas(30000000)] -fn test_set_approval_for_all() { - // sets approval status which can be queried via is_approved_for_all - let (world, erc1155) = deploy_default(); - impersonate(USER1()); - - erc1155.set_approval_for_all(PROXY(), true); - assert(erc1155.is_approved_for_all(USER1(), PROXY()) == true, 'should be true'); -} - -#[test] -#[available_gas(30000000)] -fn test_set_approval_for_all_emit_event() { - // set_approval_for_all emits ApprovalForAll event - let (world, erc1155) = deploy_default(); - impersonate(USER1()); - - erc1155.set_approval_for_all(PROXY(), true); - - // ApprovalForAll - assert( - @starknet::testing::pop_log(erc1155.contract_address) - .unwrap() == @Event::ApprovalForAll( - ApprovalForAll { owner: USER1(), operator: PROXY(), approved: true } - ), - 'invalid ApprovalForAll event' - ); -} - - -#[test] -#[available_gas(30000000)] -fn test_set_unset_approval_for_all() { - // sets approval status which can be queried via is_approved_for_all - let (world, erc1155) = deploy_default(); - impersonate(USER1()); - - erc1155.set_approval_for_all(PROXY(), true); - assert(erc1155.is_approved_for_all(USER1(), PROXY()) == true, 'should be true'); - erc1155.set_approval_for_all(PROXY(), false); - assert(erc1155.is_approved_for_all(USER1(), PROXY()) == false, 'should be false'); -} - -#[test] -#[available_gas(30000000)] -#[should_panic()] -fn test_set_approval_for_all_on_self() { - // reverts if attempting to approve self as an operator - let (world, erc1155) = deploy_default(); - impersonate(USER1()); - - erc1155.set_approval_for_all(USER1(), true); // should panic -} - -// -// safe_transfer_from -// - -#[test] -#[available_gas(30000000)] -#[should_panic()] -fn test_safe_transfer_from_more_than_balance() { - // reverts when transferring more than balance - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER1()); - - erc1155.safe_transfer_from(USER1(), USER2(), 1, 999, array![]); // should panic -} - -#[test] -#[available_gas(30000000)] -#[should_panic()] -fn test_safe_transfer_to_zero() { - // reverts when transferring to zero address - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER1()); - - erc1155.safe_transfer_from(USER1(), ZERO(), 1, 1, array![]); // should panic -} - -#[test] -#[available_gas(50000000)] -fn test_safe_transfer_debit_sender() { - // debits transferred balance from sender - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER1()); - - let balance_before = erc1155.balance_of(USER1(), 1); - erc1155.safe_transfer_from(USER1(), USER2(), 1, 1, array![]); - let balance_after = erc1155.balance_of(USER1(), 1); - - assert(balance_after == balance_before - 1, 'invalid balance after'); -} - -#[test] -#[available_gas(50000000)] -fn test_safe_transfer_credit_receiver() { - // credits transferred balance to receiver - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER1()); - - let balance_before = erc1155.balance_of(USER2(), 1); - erc1155.safe_transfer_from(USER1(), USER2(), 1, 1, array![]); - let balance_after = erc1155.balance_of(USER2(), 1); - - assert(balance_after == balance_before + 1, 'invalid balance after'); -} - -#[test] -#[available_gas(50000000)] -fn test_safe_transfer_preserve_existing_balances() { - // preserves existing balances which are not transferred by multiTokenHolder - let (world, erc1155) = deploy_testcase1(); - - // impersonate user1 - impersonate(USER1()); - - let balance_before_2 = erc1155.balance_of(USER2(), 2); - let balance_before_3 = erc1155.balance_of(USER2(), 3); - erc1155.safe_transfer_from(USER1(), USER2(), 1, 1, array![]); - let balance_after_2 = erc1155.balance_of(USER2(), 2); - let balance_after_3 = erc1155.balance_of(USER2(), 3); - - assert(balance_after_2 == balance_before_2, 'should be equal'); - assert(balance_after_3 == balance_before_3, 'should be equal'); -} - -#[test] -#[available_gas(30000000)] -#[should_panic()] -fn test_safe_transfer_from_unapproved_operator() { - // when called by an operator on behalf of the multiTokenHolder - // when operator is not approved by multiTokenHolder - - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER2()); - - erc1155.safe_transfer_from(USER1(), USER2(), 1, 1, array![]); // should panic -} - -#[test] -#[available_gas(50000000)] -fn test_safe_transfer_from_approved_operator() { - // when called by an operator on behalf of the multiTokenHolder - // when operator is approved by multiTokenHolder - let (world, erc1155) = deploy_testcase1(); - - impersonate(PROXY()); - - let balance_before = erc1155.balance_of(USER1(), 1); - erc1155.safe_transfer_from(USER1(), USER2(), 1, 2, array![]); - let balance_after = erc1155.balance_of(USER1(), 1); - - assert(balance_after == balance_before - 2, 'invalid balance'); -} - -#[test] -#[available_gas(50000000)] -fn test_safe_transfer_from_approved_operator_preserve_operator_balance() { - // when called by an operator on behalf of the multiTokenHolder - // preserves operator's balances not involved in the transfer - let (world, erc1155) = deploy_testcase1(); - - impersonate(PROXY()); - - let balance_before_1 = erc1155.balance_of(PROXY(), 1); - let balance_before_2 = erc1155.balance_of(PROXY(), 2); - let balance_before_3 = erc1155.balance_of(PROXY(), 3); - erc1155.safe_transfer_from(USER1(), USER2(), 1, 2, array![]); - let balance_after_1 = erc1155.balance_of(PROXY(), 1); - let balance_after_2 = erc1155.balance_of(PROXY(), 2); - let balance_after_3 = erc1155.balance_of(PROXY(), 3); - - assert(balance_before_1 == balance_after_1, 'should be equal'); - assert(balance_before_2 == balance_after_2, 'should be equal'); - assert(balance_before_3 == balance_after_3, 'should be equal'); -} - - -#[test] -#[available_gas(50000000)] -#[should_panic] -fn test_safe_transfer_from_zero_address() { - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER1()); - - erc1155.safe_transfer_from(ZERO(), USER1(), 1, 1, array![]); -} - -// -// safe_batch_transfer_from -// - -#[test] -#[available_gas(50000000)] -#[should_panic] -fn test_safe_batch_transfer_from_more_than_balance() { - // reverts when transferring amount more than any of balances - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER1()); - - erc1155 - .safe_batch_transfer_from(USER1(), USER2(), array![1, 2, 3], array![1, 999, 1], array![]); -} - - -#[test] -#[available_gas(50000000)] -#[should_panic] -fn test_safe_batch_transfer_from_mismatching_array_len() { - // reverts when ids array length doesn't match amounts array length - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER1()); - - erc1155.safe_batch_transfer_from(USER1(), USER2(), array![1, 2, 3], array![1, 1], array![]); -} - - -#[test] -#[available_gas(50000000)] -#[should_panic] -fn test_safe_batch_transfer_from_to_zero_address() { - // reverts when transferring to zero address - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER1()); - - erc1155.safe_batch_transfer_from(USER1(), ZERO(), array![1, 2], array![1, 1], array![]); -} - - -#[test] -#[available_gas(60000000)] -fn test_safe_batch_transfer_from_debits_sender() { - // debits transferred balances from sender - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER1()); - - let balance_before_1 = erc1155.balance_of(USER1(), 1); - let balance_before_2 = erc1155.balance_of(USER1(), 2); - let balance_before_3 = erc1155.balance_of(USER1(), 3); - erc1155 - .safe_batch_transfer_from(USER1(), USER2(), array![1, 2, 3], array![1, 10, 20], array![]); - let balance_after_1 = erc1155.balance_of(USER1(), 1); - let balance_after_2 = erc1155.balance_of(USER1(), 2); - let balance_after_3 = erc1155.balance_of(USER1(), 3); - - assert(balance_before_1 - 1 == balance_after_1, 'invalid balance'); - assert(balance_before_2 - 10 == balance_after_2, 'invalid balance'); - assert(balance_before_3 - 20 == balance_after_3, 'invalid balance'); -} - - -#[test] -#[available_gas(60000000)] -fn test_safe_batch_transfer_from_credits_recipient() { - // credits transferred balances to receiver - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER1()); - - let balance_before_1 = erc1155.balance_of(USER2(), 1); - let balance_before_2 = erc1155.balance_of(USER2(), 2); - let balance_before_3 = erc1155.balance_of(USER2(), 3); - erc1155 - .safe_batch_transfer_from(USER1(), USER2(), array![1, 2, 3], array![1, 10, 20], array![]); - let balance_after_1 = erc1155.balance_of(USER2(), 1); - let balance_after_2 = erc1155.balance_of(USER2(), 2); - let balance_after_3 = erc1155.balance_of(USER2(), 3); - - assert(balance_before_1 + 1 == balance_after_1, 'invalid balance'); - assert(balance_before_2 + 10 == balance_after_2, 'invalid balance'); - assert(balance_before_1 + 20 == balance_after_3, 'invalid balance'); -} - - -#[test] -#[available_gas(50000000)] -#[should_panic] -fn test_safe_batch_transfer_from_unapproved_operator() { - // when called by an operator on behalf of the multiTokenHolder - // when operator is not approved by multiTokenHolder - - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER2()); - - erc1155.safe_batch_transfer_from(USER1(), USER2(), array![1, 2], array![1, 10], array![]); -} - -#[test] -#[available_gas(60000000)] -fn test_safe_batch_transfer_from_approved_operator_preserve_operator_balance() { - // when called by an operator on behalf of the multiTokenHolder - // preserves operator's balances not involved in the transfer - - let (world, erc1155) = deploy_testcase1(); - - impersonate(PROXY()); - - let balance_before_1 = erc1155.balance_of(PROXY(), 1); - let balance_before_2 = erc1155.balance_of(PROXY(), 2); - let balance_before_3 = erc1155.balance_of(PROXY(), 3); - - erc1155 - .safe_batch_transfer_from(USER1(), USER2(), array![1, 2, 3], array![1, 10, 20], array![]); - - let balance_after_1 = erc1155.balance_of(PROXY(), 1); - let balance_after_2 = erc1155.balance_of(PROXY(), 2); - let balance_after_3 = erc1155.balance_of(PROXY(), 3); - - assert(balance_before_1 == balance_after_1, 'should be equal'); - assert(balance_before_2 == balance_after_2, 'should be equal'); - assert(balance_before_3 == balance_after_3, 'should be equal'); -} - -#[test] -#[available_gas(50000000)] -#[should_panic] -fn test_safe_batch_transfer_from_zero_address() { - let (world, erc1155) = deploy_testcase1(); - - impersonate(USER1()); - - erc1155.safe_batch_transfer_from(ZERO(), USER1(), array![1, 2], array![1, 1], array![]); -} - - -#[test] -#[available_gas(50000000)] -fn test_safe_batch_transfer_emit_transfer_batch_event() { - let (world, erc1155) = deploy_default(); - - // user1 token_id 1 x 10 - erc1155.mint(USER1(), 1, 10, array![]); - // user1 token_id 2 x 20 - erc1155.mint(USER1(), 2, 20, array![]); - - impersonate(USER1()); - - erc1155.safe_batch_transfer_from(USER1(), USER2(), array![1, 2], array![1, 10], array![]); - - let _: Event = starknet::testing::pop_log(erc1155.contract_address) - .unwrap(); // unpop erc1155.mint(USER1(), 1, 10, array![]); - let _: Event = starknet::testing::pop_log(erc1155.contract_address) - .unwrap(); // unpop erc1155.mint(USER1(), 2, 20, array![]); - - // TransferBatch - assert( - @starknet::testing::pop_log(erc1155.contract_address) - .unwrap() == @Event::TransferBatch( - TransferBatch { - operator: USER1(), - from: USER1(), - to: USER2(), - ids: array![1, 2], - values: array![1, 10] - } - ), - 'invalid TransferBatch event' - ); -} - - -// -// burn -// - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_burn_non_existing_token_id() { - //reverts when burning a non-existent token id - let (world, erc1155) = deploy_default(); - - impersonate(USER1()); - erc1155.burn(USER1(), 69, 1); // should panic -} - - -#[test] -#[available_gas(90000000)] -fn test_burn_emit_transfer_single_event() { - // burn should emit event - let (world, erc1155) = deploy_default(); - - erc1155.mint(USER1(), 69, 5, array![]); - assert(erc1155.balance_of(USER1(), 69) == 5, 'invalid balance'); - - impersonate(USER1()); - - erc1155.burn(USER1(), 69, 1); - assert(erc1155.balance_of(USER1(), 69) == 4, 'invalid balance'); - - let _: Event = starknet::testing::pop_log(erc1155.contract_address) - .unwrap(); // unpop erc1155.mint(USER1(), 69,5,array![]) - - // TransferSingle - assert( - @starknet::testing::pop_log(erc1155.contract_address) - .unwrap() == @Event::TransferSingle( - TransferSingle { operator: USER1(), from: USER1(), to: ZERO(), id: 69, value: 1 } - ), - 'invalid TransferSingle event' - ); -} - - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_burn_more_than_owned() { - // reverts when burning more tokens than owned - let (world, erc1155) = deploy_default(); - erc1155.mint(USER1(), 69, 10, array![]); - - impersonate(USER1()); - - erc1155.burn(USER1(), 69, 1); - erc1155.burn(USER1(), 69, 10); // should panic -} -// TODO : to be continued - -// TODO : add test if we support IERC1155Receiver - - diff --git a/crates/dojo-erc/src/tests/test_erc721.cairo b/crates/dojo-erc/src/tests/test_erc721.cairo deleted file mode 100644 index fc23abc4f9..0000000000 --- a/crates/dojo-erc/src/tests/test_erc721.cairo +++ /dev/null @@ -1,862 +0,0 @@ -use core::zeroable::Zeroable; -use core::traits::{Into, Default}; -use array::ArrayTrait; -use serde::Serde; -use starknet::ContractAddress; -use starknet::testing::set_contract_address; -use option::OptionTrait; - -use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - -use dojo_erc::tests::test_utils::impersonate; -use dojo_erc::tests::test_erc721_utils::{ - spawn_world, deploy_erc721, deploy_default, deploy_testcase1, USER1, USER2, USER3, DEPLOYER, - ZERO, PROXY -}; - - -use dojo_erc::erc165::interface::IERC165_ID; -use dojo_erc::erc721::interface::{ - IERC721, IERC721ADispatcher, IERC721ADispatcherTrait, IERC721_ID, IERC721_METADATA_ID -}; -use dojo_erc::erc721::erc721::ERC721::{Event, Transfer, Approval, ApprovalForAll}; -// actually it's possible to mint -> burn -> mint -> ... -// todo : add Minted component to keep track of minted ids - -#[test] -#[available_gas(30000000)] -fn test_deploy() { - let world = spawn_world(DEPLOYER()); - let erc721_address = deploy_erc721(world, DEPLOYER(), 'name', 'symbol', 'uri', 'seed-42'); - let erc721 = IERC721ADispatcher { contract_address: erc721_address }; - - assert(erc721.owner() == DEPLOYER(), 'invalid owner'); - assert(erc721.name() == 'name', 'invalid name'); - assert(erc721.symbol() == 'symbol', 'invalid symbol'); -} - - -#[test] -#[available_gas(30000000)] -fn test_deploy_default() { - let (world, erc721) = deploy_default(); - assert(erc721.name() == 'name', 'invalid name'); -} - -// -// supports_interface -// - -#[test] -#[available_gas(30000000)] -fn test_should_support_interfaces() { - let (world, erc721) = deploy_default(); - - assert(erc721.supports_interface(IERC165_ID) == true, 'should support erc165'); - assert(erc721.supports_interface(IERC721_ID) == true, 'should support erc721'); - assert( - erc721.supports_interface(IERC721_METADATA_ID) == true, 'should support erc721_metadata' - ); -} - - -// -// behaves like an ERC721 -// - -// -// balance_of -// - -use debug::PrintTrait; - -#[test] -#[available_gas(60000000)] -fn test_balance_of_with_tokens() { - // returns the amount of tokens owned by the given address - - let (world, erc721) = deploy_testcase1(); - assert(erc721.balance_of(USER1()) == 3, 'should be 3'); - assert(erc721.balance_of(PROXY()) == 4, 'should be 4'); -} - -#[test] -#[available_gas(60000000)] -fn test_balance_of_with_no_tokens() { - // when the given address does not own any tokens - - let (world, erc721) = deploy_testcase1(); - assert(erc721.balance_of(USER3()) == 0, 'should be 0'); -} - - -#[test] -#[available_gas(50000000)] -#[should_panic] -fn test_balance_of_zero_address() { - // when querying the zero address - - let (world, erc721) = deploy_testcase1(); - erc721.balance_of(ZERO()); -} - -// -// owner_of -// - -#[test] -#[available_gas(90000000)] -fn test_owner_of_existing_id() { - // when the given token ID was tracked by this token = for existing id - - let (world, erc721) = deploy_testcase1(); - assert(erc721.owner_of(1) == USER1(), 'should be user1'); - assert(erc721.owner_of(2) == USER1(), 'should be user1'); - assert(erc721.owner_of(3) == USER1(), 'should be user1'); - - assert(erc721.owner_of(10) == PROXY(), 'should be proxy'); - assert(erc721.owner_of(11) == PROXY(), 'should be proxy'); - assert(erc721.owner_of(12) == PROXY(), 'should be proxy'); - assert(erc721.owner_of(13) == PROXY(), 'should be proxy'); -} - - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_owner_of_non_existing_id() { - // when the given token ID was not tracked by this token = non existing id - - let (world, erc721) = deploy_testcase1(); - let owner_of_0 = erc721.owner_of(0); // should panic -} - -// -// transfers -// - -#[test] -#[available_gas(90000000)] -fn test_transfer_ownership() { - // transfers the ownership of the given token ID to the given address - - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - let owner_of_1 = erc721.owner_of(1); - // transfer token_id 1 to user2 - erc721.transfer(USER2(), 1); - assert(erc721.owner_of(1) == USER2(), 'invalid owner'); -} - -#[test] -#[available_gas(90000000)] -fn test_transfer_event() { - // emits a Transfer event - - let (world, erc721) = deploy_default(); - - // mint - erc721.mint(USER1(), 42); - - impersonate(USER1()); - - // transfer token_id 1 to user2 - erc721.transfer(USER2(), 42); - - impersonate(USER2()); - erc721.burn(42); - - // mint - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::Transfer(Transfer { from: ZERO(), to: USER1(), token_id: 42 }), - 'invalid Transfer event' - ); - // transfer - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::Transfer(Transfer { from: USER1(), to: USER2(), token_id: 42 }), - 'invalid Transfer event' - ); - // burn - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::Transfer(Transfer { from: USER2(), to: ZERO(), token_id: 42 }), - 'invalid Transfer event' - ); -} - - -#[test] -#[available_gas(90000000)] -fn test_transfer_clear_approval() { - // clears the approval for the token ID - - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - erc721.approve(PROXY(), 1); - assert(erc721.get_approved(1) == PROXY(), 'should be proxy'); - - // transfer token_id 1 to user2 - erc721.transfer(USER2(), 1); - assert(erc721.get_approved(1).is_zero(), 'should be zero'); -} - -#[test] -#[available_gas(90000000)] -fn test_transfer_adjusts_owners_balances() { - // adjusts owners balances - - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - let balance_user1_before = erc721.balance_of(USER1()); - let balance_user2_before = erc721.balance_of(USER2()); - - // transfer token_id 1 to user2 - erc721.transfer(USER2(), 1); - - let balance_user1_after = erc721.balance_of(USER1()); - let balance_user2_after = erc721.balance_of(USER2()); - - assert(balance_user1_after == balance_user1_before - 1, 'invalid user1 balance'); - assert(balance_user2_after == balance_user2_before + 1, 'invalid user2 balance'); -} - - -#[test] -#[available_gas(90000000)] -fn test_transfer_from_approved() { - // when called by the approved individual - - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - //user1 approve user2 for token_id 2 - erc721.approve(USER2(), 2); - - impersonate(USER2()); - - erc721.transfer_from(USER1(), USER2(), 2); - assert(erc721.owner_of(2) == USER2(), 'invalid owner'); -} - -#[test] -#[available_gas(90000000)] -fn test_transfer_from_approved_operator() { - // when called by the operator - - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - //user1 set_approval_for_all for proxy - erc721.set_approval_for_all(PROXY(), true); - - impersonate(PROXY()); - - erc721.transfer_from(USER1(), USER2(), 2); - assert(erc721.owner_of(2) == USER2(), 'invalid owner'); -} - -#[test] -#[available_gas(90000000)] -fn test_transfer_from_owner_without_approved() { - // when called by the owner without an approved user - - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - erc721.approve(ZERO(), 2); - - erc721.transfer_from(USER1(), USER2(), 2); - assert(erc721.owner_of(2) == USER2(), 'invalid owner'); -} - - -#[test] -#[available_gas(90000000)] -fn test_transfer_to_owner() { - // when sent to the owner - - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - let balance_before = erc721.balance_of(USER1()); - - assert(erc721.owner_of(3) == USER1(), 'invalid owner'); - erc721.transfer(USER1(), 3); - - // keeps ownership of the token - assert(erc721.owner_of(3) == USER1(), 'invalid owner'); - - // clears the approval for the token ID - assert(erc721.get_approved(3) == ZERO(), 'invalid approved'); - - //emits only a transfer event : cumbersome to test with pop_log - - //keeps the owner balance - let balance_after = erc721.balance_of(USER1()); - assert(balance_before == balance_after, 'invalid balance') -} - - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_transfer_when_previous_owner_is_incorrect() { - // when the address of the previous owner is incorrect - - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - //user2 owner token_id 10 - erc721.transfer_from(USER1(), PROXY(), 10); // should panic -} - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_transfer_when_sender_not_authorized() { - // when the sender is not authorized for the token id - let (world, erc721) = deploy_testcase1(); - - impersonate(PROXY()); - - //proxy is not authorized for USER2 - erc721.transfer_from(USER2(), PROXY(), 20); // should panic -} - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_transfer_when_token_id_doesnt_exists() { - // when the sender is not authorized for the token id - let (world, erc721) = deploy_testcase1(); - - impersonate(PROXY()); - - //proxy is authorized for USER1 but token_id 50 doesnt exists - erc721.transfer_from(USER1(), PROXY(), 50); // should panic -} - - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_transfer_to_address_zero() { - // when the address to transfer the token to is the zero address - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - erc721.transfer(ZERO(), 1); // should panic -} - -// -// approval -// - -// when clearing approval - -#[test] -#[available_gas(90000000)] -fn test_approval_when_clearing_with_prior_approval() { - // -when there was a prior approval - let (world, erc721) = deploy_default(); - - erc721.mint(USER1(), 42); - - impersonate(USER1()); - - erc721.approve(PROXY(), 42); - - //revoke approve - erc721.approve(ZERO(), 42); - - // clears approval for the token - assert(erc721.get_approved(42) == ZERO(), 'invalid approved'); - - // emits an approval event - let _: Event = starknet::testing::pop_log(erc721.contract_address).unwrap(); // unpop mint - let _: Event = starknet::testing::pop_log(erc721.contract_address) - .unwrap(); // unpop approve PROXY - - // approve ZERO - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::Approval(Approval { owner: USER1(), to: ZERO(), token_id: 42 }), - 'invalid Approval event' - ); -} - -#[test] -#[available_gas(90000000)] -fn test_approval_when_clearing_without_prior_approval() { - // when clearing approval - // -when there was no prior approval - let (world, erc721) = deploy_default(); - - erc721.mint(USER1(), 42); - - impersonate(USER1()); - - //revoke approve - erc721.approve(ZERO(), 42); - - // updates approval for the token - assert(erc721.get_approved(42) == ZERO(), 'invalid approved'); - - let _: Event = starknet::testing::pop_log(erc721.contract_address).unwrap(); // unpop mint - - // approve ZERO - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::Approval(Approval { owner: USER1(), to: ZERO(), token_id: 42 }), - 'invalid Approval event' - ); -} - - -// when approving a non-zero address - -#[test] -#[available_gas(90000000)] -fn test_approval_non_zero_address_with_prior_approval() { - // -when there was a prior approval - let (world, erc721) = deploy_default(); - - erc721.mint(USER1(), 42); - - impersonate(USER1()); - erc721.approve(PROXY(), 42); - - // user1 approves user3 - erc721.approve(USER3(), 42); - - // set approval for the token - assert(erc721.get_approved(42) == USER3(), 'invalid approved'); - - // emits an approval event - let _: Event = starknet::testing::pop_log(erc721.contract_address).unwrap(); // unpop mint - let _: Event = starknet::testing::pop_log(erc721.contract_address) - .unwrap(); // unpop approve PROXY - - // approve USER3 - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::Approval(Approval { owner: USER1(), to: USER3(), token_id: 42 }), - 'invalid Approval event' - ); -} - -#[test] -#[available_gas(90000000)] -fn test_approval_non_zero_address_with_no_prior_approval() { - // -when there was no prior approval - let (world, erc721) = deploy_default(); - - erc721.mint(USER1(), 42); - - impersonate(USER1()); - - // user1 approves user3 - erc721.approve(USER3(), 42); - - // set approval for the token - assert(erc721.get_approved(42) == USER3(), 'invalid approved'); - - // emits an approval event - let _: Event = starknet::testing::pop_log(erc721.contract_address).unwrap(); // unpop mint - - // approve USER3 - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::Approval(Approval { owner: USER1(), to: USER3(), token_id: 42 }), - 'invalid Approval event' - ); -} - - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_approval_self_approve() { - // when the address that receives the approval is the owner - let (world, erc721) = deploy_default(); - - erc721.mint(USER1(), 42); - - impersonate(USER1()); - - // user1 approves user1 - erc721.approve(USER1(), 42); // should panic -} - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_approval_not_owned() { - // when the sender does not own the given token ID - - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - // user1 approves user2 for token 20 - erc721.approve(USER2(), 20); // should panic -} - - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_approval_from_approved_sender() { - // when the sender is approved for the given token ID - - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - // user1 approve user3 - erc721.approve(USER3(), 1); - - impersonate(USER3()); - - // (ERC721: approve caller is not token owner or approved for all) - erc721.approve(USER2(), 1); // should panic -} - - -#[test] -#[available_gas(90000000)] -fn test_approval_from_approved_operator() { - // when the sender is an operator - let (world, erc721) = deploy_default(); - - erc721.mint(USER1(), 50); - - impersonate(USER1()); - - erc721.set_approval_for_all(PROXY(), true); - - impersonate(PROXY()); - - // proxy approves user2 for token 20 - erc721.approve(USER2(), 50); - - assert(erc721.get_approved(50) == USER2(), 'invalid approval'); - - let _: Event = starknet::testing::pop_log(erc721.contract_address).unwrap(); // unpop mint - let _: Event = starknet::testing::pop_log(erc721.contract_address) - .unwrap(); // unpop set_approval_for_all - - // approve - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::Approval(Approval { owner: USER1(), to: USER2(), token_id: 50 }), - 'invalid Approval event' - ); -} - - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_approval_unexisting_id() { - // when the given token ID does not exist - let (world, erc721) = deploy_testcase1(); - - impersonate(USER1()); - - // user1 approve user3 - erc721.approve(USER3(), 69); // should panic -} - -// -// approval_for_all -// - -#[test] -#[available_gas(90000000)] -fn test_approval_for_all_operator_is_not_owner_no_operator_approval() { - // when the operator willing to approve is not the owner - // -when there is no operator approval set by the sender - let (world, erc721) = deploy_default(); - - impersonate(USER2()); - - // user2 set_approval_for_all PROXY - erc721.set_approval_for_all(PROXY(), true); - - assert(erc721.is_approved_for_all(USER2(), PROXY()) == true, 'invalid is_approved_for_all'); - - // ApproveForAll - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::ApprovalForAll( - ApprovalForAll { owner: USER2(), operator: PROXY(), approved: true } - ), - 'invalid ApprovalForAll event' - ); -} - -#[test] -#[available_gas(90000000)] -fn test_approval_for_all_operator_is_not_owner_from_not_approved() { - // when the operator willing to approve is not the owner - // -when the operator was set as not approved - let (world, erc721) = deploy_default(); - - impersonate(USER2()); - - erc721.set_approval_for_all(PROXY(), false); - - // user2 set_approval_for_all PROXY - erc721.set_approval_for_all(PROXY(), true); - - assert(erc721.is_approved_for_all(USER2(), PROXY()) == true, 'invalid is_approved_for_all'); - - let _: Event = starknet::testing::pop_log(erc721.contract_address) - .unwrap(); // unpop set_approval_for_all(PROXY(), false) - - // ApproveForAll - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::ApprovalForAll( - ApprovalForAll { owner: USER2(), operator: PROXY(), approved: true } - ), - 'invalid ApprovalForAll event' - ); -} - -#[test] -#[available_gas(90000000)] -fn test_approval_for_all_operator_is_not_owner_can_unset_approval_for_all() { - // when the operator willing to approve is not the owner - // can unset the operator approval - let (world, erc721) = deploy_default(); - - impersonate(USER2()); - - erc721.set_approval_for_all(PROXY(), false); - erc721.set_approval_for_all(PROXY(), true); - assert(erc721.is_approved_for_all(USER2(), PROXY()) == true, 'invalid is_approved_for_all'); - erc721.set_approval_for_all(PROXY(), false); - assert(erc721.is_approved_for_all(USER2(), PROXY()) == false, 'invalid is_approved_for_all'); - - let _: Event = starknet::testing::pop_log(erc721.contract_address) - .unwrap(); // unpop set_approval_for_all(PROXY(), false) - let _: Event = starknet::testing::pop_log(erc721.contract_address) - .unwrap(); // unpop set_approval_for_all(PROXY(), true) - - // ApproveForAll - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::ApprovalForAll( - ApprovalForAll { owner: USER2(), operator: PROXY(), approved: false } - ), - 'invalid ApprovalForAll event' - ); -} - -#[test] -#[available_gas(90000000)] -fn test_approval_for_all_operator_with_operator_already_approved() { - // when the operator willing to approve is not the owner - // when the operator was already approved - let (world, erc721) = deploy_default(); - - impersonate(USER2()); - - erc721.set_approval_for_all(PROXY(), true); - assert(erc721.is_approved_for_all(USER2(), PROXY()) == true, 'invalid is_approved_for_all'); - erc721.set_approval_for_all(PROXY(), true); - assert(erc721.is_approved_for_all(USER2(), PROXY()) == true, 'invalid is_approved_for_all'); - - let _: Event = starknet::testing::pop_log(erc721.contract_address) - .unwrap(); // unpop set_approval_for_all(PROXY(), true) - - // ApproveForAll - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::ApprovalForAll( - ApprovalForAll { owner: USER2(), operator: PROXY(), approved: true } - ), - 'invalid ApprovalForAll event' - ); -} - - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_approval_for_all_with_owner_as_operator() { - // when the operator is the owner - - let (world, erc721) = deploy_default(); - - impersonate(USER1()); - - erc721.set_approval_for_all(USER1(), true); // should panic -} - - -// -// get_approved -// - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_get_approved_unexisting_token() { - let (world, erc721) = deploy_default(); - - erc721.get_approved(420); // should panic -} - - -#[test] -#[available_gas(90000000)] -fn test_get_approved_with_existing_token() { - let (world, erc721) = deploy_default(); - - erc721.mint(USER1(), 420); - assert(erc721.get_approved(420) == ZERO(), 'invalid get_approved'); -} - - -#[test] -#[available_gas(90000000)] -fn test_get_approved_with_existing_token_and_approval() { - let (world, erc721) = deploy_default(); - - erc721.mint(USER1(), 420); - - impersonate(USER1()); - - erc721.approve(PROXY(), 420); - assert(erc721.get_approved(420) == PROXY(), 'invalid get_approved'); -} - -// -// mint -// - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_mint_to_address_zero() { - // reverts with a null destination address - - let (world, erc721) = deploy_default(); - - erc721.mint(ZERO(), 69); // should panic -} - - -#[test] -#[available_gas(90000000)] -fn test_mint() { - // reverts with a null destination address - - let (world, erc721) = deploy_default(); - - erc721.mint(USER1(), 69); - - assert(erc721.balance_of(USER1()) == 1, 'invalid balance'); - - // Transfer - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::Transfer(Transfer { from: ZERO(), to: USER1(), token_id: 69 }), - 'invalid Transfer event' - ); -} - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_mint_existing_token_id() { - // reverts with a null destination address - - let (world, erc721) = deploy_default(); - - erc721.mint(USER1(), 69); - erc721.mint(USER1(), 69); //should panic -} - - -// -// burn -// - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_burn_non_existing_token_id() { - //reverts when burning a non-existent token id - let (world, erc721) = deploy_default(); - erc721.burn(69); // should panic -} - - -#[test] -#[available_gas(90000000)] -fn test_burn_emit_events() { - // burn should emit event - let (world, erc721) = deploy_default(); - - erc721.mint(USER1(), 69); - assert(erc721.balance_of(USER1()) == 1, 'invalid balance'); - - impersonate(USER1()); - - erc721.burn(69); - assert(erc721.balance_of(USER1()) == 0, 'invalid balance'); - - let _: Event = starknet::testing::pop_log(erc721.contract_address) - .unwrap(); // unpop erc721.mint(USER1(), 69) - - // Transfer - assert( - @starknet::testing::pop_log(erc721.contract_address) - .unwrap() == @Event::Transfer(Transfer { from: USER1(), to: ZERO(), token_id: 69 }), - 'invalid Transfer event' - ); -} - - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_burn_same_id_twice() { - // reverts when burning a token id that has been deleted - let (world, erc721) = deploy_default(); - erc721.mint(USER1(), 69); - erc721.burn(69); - erc721.burn(69); // should panic -} - -// -// token_uri -// - -#[test] -#[available_gas(90000000)] -#[should_panic] -fn test_token_uri_for_non_existing_token_id() { - // reverts when queried for non existent token id - let (world, erc721) = deploy_default(); - erc721.token_uri(1234); // should panic -} - diff --git a/crates/dojo-erc/src/tests/utils.cairo b/crates/dojo-erc/src/tests/utils.cairo deleted file mode 100644 index 99e956694f..0000000000 --- a/crates/dojo-erc/src/tests/utils.cairo +++ /dev/null @@ -1,32 +0,0 @@ -use core::result::ResultTrait; -use starknet::class_hash::Felt252TryIntoClassHash; -use starknet::ContractAddress; -use starknet::testing; - -fn deploy(contract_class_hash: felt252, calldata: Array) -> ContractAddress { - let (address, _) = starknet::deploy_syscall( - contract_class_hash.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); - address -} - -/// Pop the earliest unpopped logged event for the contract as the requested type -/// and checks there's no more data left on the event, preventing unaccounted params. -/// Indexed event members are currently not supported, so they are ignored. -fn pop_log, impl TEvent: starknet::Event>( - address: ContractAddress -) -> Option { - let (mut keys, mut data) = testing::pop_log_raw(address)?; - let ret = starknet::Event::deserialize(ref keys, ref data); - assert(data.is_empty(), 'Event has extra data'); - ret -} - -fn assert_no_events_left(address: ContractAddress) { - assert(testing::pop_log_raw(address).is_none(), 'Events remaining on queue'); -} - -fn drop_event(address: ContractAddress) { - testing::pop_log_raw(address); -} diff --git a/crates/dojo-erc/src/token/erc1155.cairo b/crates/dojo-erc/src/token/erc1155.cairo deleted file mode 100644 index af50183ea3..0000000000 --- a/crates/dojo-erc/src/token/erc1155.cairo +++ /dev/null @@ -1,5 +0,0 @@ -mod erc1155; -mod models; -mod interface; - -use erc1155::ERC1155; \ No newline at end of file diff --git a/crates/dojo-erc/src/token/erc1155/erc1155.cairo b/crates/dojo-erc/src/token/erc1155/erc1155.cairo deleted file mode 100644 index 26ba7f23bb..0000000000 --- a/crates/dojo-erc/src/token/erc1155/erc1155.cairo +++ /dev/null @@ -1,439 +0,0 @@ -#[starknet::contract] -mod ERC1155 { - use dojo_erc::token::erc1155::models::{ - ERC1155Meta, ERC1155OperatorApproval, ERC1155Balance - }; - use dojo_erc::token::erc1155::interface; - use dojo_erc::token::erc1155::interface::{IERC1155, IERC1155CamelOnly}; - use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - use starknet::ContractAddress; - use starknet::{get_caller_address, get_contract_address}; - use array::ArrayTCloneImpl; - use zeroable::Zeroable; - use debug::PrintTrait; - - #[storage] - struct Storage { - _world: ContractAddress, - } - - #[event] - #[derive(Clone, Drop, starknet::Event)] - enum Event { - TransferSingle: TransferSingle, - TransferBatch: TransferBatch, - ApprovalForAll: ApprovalForAll - } - - #[derive(Clone, Drop, starknet::Event)] - struct TransferSingle { - operator: ContractAddress, - from: ContractAddress, - to: ContractAddress, - id: u256, - value: u256 - } - - #[derive(Clone, Drop, starknet::Event)] - struct TransferBatch { - operator: ContractAddress, - from: ContractAddress, - to: ContractAddress, - ids: Array, - values: Array - } - - #[derive(Clone, Drop, starknet::Event)] - struct ApprovalForAll { - owner: ContractAddress, - operator: ContractAddress, - approved: bool - } - - mod Errors { - const INVALID_TOKEN_ID: felt252 = 'ERC1155: invalid token ID'; - const INVALID_ACCOUNT: felt252 = 'ERC1155: invalid account'; - const UNAUTHORIZED: felt252 = 'ERC1155: unauthorized caller'; - const SELF_APPROVAL: felt252 = 'ERC1155: self approval'; - const INVALID_RECEIVER: felt252 = 'ERC1155: invalid receiver'; - const WRONG_SENDER: felt252 = 'ERC1155: wrong sender'; - const SAFE_MINT_FAILED: felt252 = 'ERC1155: safe mint failed'; - const SAFE_TRANSFER_FAILED: felt252 = 'ERC1155: safe transfer failed'; - const INVALID_ARRAY_LENGTH: felt252 = 'ERC1155: invalid array length'; - const INSUFFICIENT_BALANCE: felt252 = 'ERC1155: insufficient balance'; - } - - #[constructor] - fn constructor( - ref self: ContractState, - world: ContractAddress, - name: felt252, - symbol: felt252, - base_uri: felt252, - ) { - self._world.write(world); - self.initializer(name, symbol, base_uri); - } - - // - // External - // - - // #[external(v0)] - // impl SRC5Impl of ISRC5 { - // fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - // let unsafe_state = src5::SRC5::unsafe_new_contract_state(); - // src5::SRC5::SRC5Impl::supports_interface(@unsafe_state, interface_id) - // } - // } - - // #[external(v0)] - // impl SRC5CamelImpl of ISRC5Camel { - // fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - // let unsafe_state = src5::SRC5::unsafe_new_contract_state(); - // src5::SRC5::SRC5CamelImpl::supportsInterface(@unsafe_state, interfaceId) - // } - // } - - #[external(v0)] - impl ERC1155MetadataImpl of interface::IERC1155Metadata { - fn name(self: @ContractState) -> felt252 { - self.get_meta().name - } - - fn symbol(self: @ContractState) -> felt252 { - self.get_meta().symbol - } - - fn uri(self: @ContractState, token_id: u256) -> felt252 { - //assert(self._exists(token_id), Errors::INVALID_TOKEN_ID); - // TODO : concat with id - self.get_uri(token_id) - } - } - - - #[external(v0)] - impl ERC1155Impl of interface::IERC1155 { - fn balance_of(self: @ContractState, account: ContractAddress, id: u256) -> u256 { - assert(account.is_non_zero(), Errors::INVALID_ACCOUNT); - self.get_balance(account, id).amount - } - - fn balance_of_batch( - self: @ContractState, accounts: Array, ids: Array - ) -> Array { - assert(ids.len() == accounts.len(), Errors::INVALID_ARRAY_LENGTH); - - let mut batch_balances = array![]; - let mut index = 0; - loop { - if index == ids.len() { - break batch_balances.clone(); - } - batch_balances.append(self.balance_of(*accounts.at(index), *ids.at(index))); - index += 1; - } - } - - fn set_approval_for_all( - ref self: ContractState, operator: ContractAddress, approved: bool - ) { - self._set_approval_for_all(get_caller_address(), operator, approved) - } - - fn is_approved_for_all( - self: @ContractState, account: ContractAddress, operator: ContractAddress - ) -> bool { - self.get_operator_approval(account, operator).approved - } - - fn safe_transfer_from( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - id: u256, - amount: u256, - data: Array - ) { - assert(to.is_non_zero(), Errors::INVALID_RECEIVER); - assert(from.is_non_zero(), Errors::WRONG_SENDER); - assert( - self._is_approved_for_all_or_owner(from, get_caller_address()), Errors::UNAUTHORIZED - ); - - self._safe_transfer_from(from, to, id, amount, data); - } - - fn safe_batch_transfer_from( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - ids: Array, - amounts: Array, - data: Array - ) { - assert(to.is_non_zero(), Errors::INVALID_RECEIVER); - assert(from.is_non_zero(), Errors::WRONG_SENDER); - assert( - self._is_approved_for_all_or_owner(from, get_caller_address()), Errors::UNAUTHORIZED - ); - - self._safe_batch_transfer_from(from, to, ids, amounts, data); - } - } - - #[external(v0)] - impl ERC1155CamelOnlyImpl of interface::IERC1155CamelOnly { - fn balanceOf(self: @ContractState, account: ContractAddress, id: u256) -> u256 { - ERC1155Impl::balance_of(self, account, id) - } - - fn balanceOfBatch( - self: @ContractState, accounts: Array, ids: Array - ) -> Array { - ERC1155Impl::balance_of_batch(self, accounts, ids) - } - - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) { - ERC1155Impl::set_approval_for_all(ref self, operator, approved); - } - fn isApprovedForAll( - self: @ContractState, account: ContractAddress, operator: ContractAddress - ) -> bool { - ERC1155Impl::is_approved_for_all(self, account, operator) - } - fn safeTransferFrom( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - id: u256, - amount: u256, - data: Array - ) { - ERC1155Impl::safe_transfer_from(ref self, from, to, id, amount, data); - } - fn safeBatchTransferFrom( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - ids: Array, - amounts: Array, - data: Array - ) { - ERC1155Impl::safe_batch_transfer_from(ref self, from, to, ids, amounts, data); - } - } - - // - // Internal - // - - #[generate_trait] - impl WorldInteractionsImpl of WorldInteractionsTrait { - fn world(self: @ContractState) -> IWorldDispatcher { - IWorldDispatcher { contract_address: self._world.read() } - } - - fn get_meta(self: @ContractState) -> ERC1155Meta { - get!(self.world(), get_contract_address(), ERC1155Meta) - } - - fn get_uri(self: @ContractState, token_id: u256) -> felt252 { - // TODO : concat with id when we have string type - self.get_meta().base_uri - } - - fn get_balance(self: @ContractState, account: ContractAddress, id: u256) -> ERC1155Balance { - get!(self.world(), (get_contract_address(), account, id), ERC1155Balance) - } - - fn get_operator_approval( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> ERC1155OperatorApproval { - get!(self.world(), (get_contract_address(), owner, operator), ERC1155OperatorApproval) - } - - fn set_operator_approval( - ref self: ContractState, - owner: ContractAddress, - operator: ContractAddress, - approved: bool - ) { - set!( - self.world(), - ERC1155OperatorApproval { token: get_contract_address(), owner, operator, approved } - ); - self.emit_event(ApprovalForAll { owner, operator, approved }); - } - - fn set_balance(ref self: ContractState, account: ContractAddress, id: u256, amount: u256) { - set!( - self.world(), ERC1155Balance { token: get_contract_address(), account, id, amount } - ); - } - - fn update_balances( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - id: u256, - amount: u256, - ) { - self.set_balance(from, id, self.get_balance(from, id).amount - amount); - self.set_balance(to, id, self.get_balance(to, id).amount + amount); - } - - fn emit_event< - S, impl IntoImp: traits::Into, impl SDrop: Drop, impl SClone: Clone - >( - ref self: ContractState, event: S - ) { - self.emit(event.clone()); - emit!(self.world(), event); - } - } - - #[generate_trait] - impl InternalImpl of InternalTrait { - fn initializer(ref self: ContractState, name: felt252, symbol: felt252, base_uri: felt252) { - let meta = ERC1155Meta { token: get_contract_address(), name, symbol, base_uri }; - set!(self.world(), (meta)); - // let mut unsafe_state = src5::SRC5::unsafe_new_contract_state(); - // src5::SRC5::InternalImpl::register_interface(ref unsafe_state, interface::IERC721_ID); - // src5::SRC5::InternalImpl::register_interface( - // ref unsafe_state, interface::IERC721_METADATA_ID - // ); - } - - fn _is_approved_for_all_or_owner( - self: @ContractState, from: ContractAddress, caller: ContractAddress - ) -> bool { - caller == from || self.is_approved_for_all(from, caller) - } - - fn _set_approval_for_all( - ref self: ContractState, - owner: ContractAddress, - operator: ContractAddress, - approved: bool - ) { - assert(owner != operator, Errors::SELF_APPROVAL); - self.set_operator_approval(owner, operator, approved); - } - - fn _safe_transfer_from( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - id: u256, - amount: u256, - data: Array - ) { - self.update_balances(from, to, id, amount); - // assert( - // _check_on_erc1155_received(from, to, id, data), Errors::SAFE_TRANSFER_FAILED - // ); - - self - .emit_event( - TransferSingle { operator: get_caller_address(), from, to, id, value: amount } - ); - } - - fn _safe_batch_transfer_from( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - ids: Array, - amounts: Array, - data: Array - ) { - assert(ids.len() == amounts.len(), Errors::INVALID_ARRAY_LENGTH); - - let mut ids_span = ids.span(); - let mut amounts_span = amounts.span(); - - loop { - if ids_span.len() == 0 { - break (); - } - let id = *ids_span.pop_front().unwrap(); - let amount = *amounts_span.pop_front().unwrap(); - self.update_balances(from, to, id, amount); - // assert( - // _check_on_erc1155_received(from, to, id, data), Errors::SAFE_TRANSFER_FAILED - // ); - }; - - self - .emit_event( - TransferBatch { operator: get_caller_address(), from, to, ids, values: amounts } - ); - } - - fn _mint(ref self: ContractState, to: ContractAddress, id: u256, amount: u256) { - assert(to.is_non_zero(), Errors::INVALID_RECEIVER); - - self.set_balance(to, id, self.get_balance(to, id).amount + amount); - - self - .emit_event( - TransferSingle { - operator: get_caller_address(), - from: Zeroable::zero(), - to, - id, - value: amount - } - ); - } - - fn _burn(ref self: ContractState, id: u256, amount: u256) { - let caller = get_caller_address(); - assert(self.get_balance(caller, id).amount >= amount, Errors::INSUFFICIENT_BALANCE); - - self.set_balance(caller, id, self.get_balance(caller, id).amount - amount); - - self - .emit_event( - TransferSingle { - operator: get_caller_address(), - from: caller, - to: Zeroable::zero(), - id, - value: amount - } - ); - } - - fn _safe_mint( - ref self: ContractState, - to: ContractAddress, - id: u256, - amount: u256, - data: Span - ) { - self._mint(to, id, amount); - // assert( - // _check_on_erc1155_received(Zeroable::zero(), to, id, data), - // Errors::SAFE_MINT_FAILED - // ); - } - } -//#[internal] -// fn _check_on_erc1155_received( -// from: ContractAddress, to: ContractAddress, token_id: u256, data: Span -// ) -> bool { -// if (DualCaseSRC5 { contract_address: to } -// .supports_interface(interface::IERC1155_RECEIVER_ID)) { -// DualCaseERC1155Receiver { contract_address: to } -// .on_erc1155_received( -// get_caller_address(), from, token_id, data -// ) == interface::IERC1155_RECEIVER_ID -// } else { -// DualCaseSRC5 { contract_address: to }.supports_interface(account::interface::ISRC6_ID) -// } -// } - -} diff --git a/crates/dojo-erc/src/token/erc1155/interface.cairo b/crates/dojo-erc/src/token/erc1155/interface.cairo deleted file mode 100644 index ecce8fb978..0000000000 --- a/crates/dojo-erc/src/token/erc1155/interface.cairo +++ /dev/null @@ -1,62 +0,0 @@ -use starknet::ContractAddress; - -#[starknet::interface] -trait IERC1155 { - fn balance_of(self: @TState, account: ContractAddress, id: u256) -> u256; - fn balance_of_batch( - self: @TState, accounts: Array, ids: Array - ) -> Array; - fn set_approval_for_all(ref self: TState, operator: ContractAddress, approved: bool); - fn is_approved_for_all( - self: @TState, account: ContractAddress, operator: ContractAddress - ) -> bool; - fn safe_transfer_from( - ref self: TState, - from: ContractAddress, - to: ContractAddress, - id: u256, - amount: u256, - data: Array - ); - fn safe_batch_transfer_from( - ref self: TState, - from: ContractAddress, - to: ContractAddress, - ids: Array, - amounts: Array, - data: Array - ); -} - -#[starknet::interface] -trait IERC1155CamelOnly { - fn balanceOf(self: @TState, account: ContractAddress, id: u256) -> u256; - fn balanceOfBatch( - self: @TState, accounts: Array, ids: Array - ) -> Array; - fn setApprovalForAll(ref self: TState, operator: ContractAddress, approved: bool); - fn isApprovedForAll(self: @TState, account: ContractAddress, operator: ContractAddress) -> bool; - fn safeTransferFrom( - ref self: TState, - from: ContractAddress, - to: ContractAddress, - id: u256, - amount: u256, - data: Array - ); - fn safeBatchTransferFrom( - ref self: TState, - from: ContractAddress, - to: ContractAddress, - ids: Array, - amounts: Array, - data: Array - ); -} - -#[starknet::interface] -trait IERC1155Metadata { - fn name(self: @TState) -> felt252; - fn symbol(self: @TState) -> felt252; - fn uri(self: @TState, token_id: u256) -> felt252; -} diff --git a/crates/dojo-erc/src/token/erc1155/models.cairo b/crates/dojo-erc/src/token/erc1155/models.cairo deleted file mode 100644 index fa021aa987..0000000000 --- a/crates/dojo-erc/src/token/erc1155/models.cairo +++ /dev/null @@ -1,33 +0,0 @@ -use starknet::ContractAddress; - -#[derive(Model, Copy, Drop, Serde)] -struct ERC1155Meta { - #[key] - token: ContractAddress, - name: felt252, - symbol: felt252, - base_uri: felt252, -} - -#[derive(Model, Copy, Drop, Serde)] -struct ERC1155OperatorApproval { - #[key] - token: ContractAddress, - #[key] - owner: ContractAddress, - #[key] - operator: ContractAddress, - approved: bool -} - - -#[derive(Model, Copy, Drop, Serde)] -struct ERC1155Balance { - #[key] - token: ContractAddress, - #[key] - account: ContractAddress, - #[key] - id: u256, - amount: u256 -} \ No newline at end of file diff --git a/crates/dojo-erc/src/token/erc20.cairo b/crates/dojo-erc/src/token/erc20.cairo deleted file mode 100644 index 238e05a1e6..0000000000 --- a/crates/dojo-erc/src/token/erc20.cairo +++ /dev/null @@ -1,331 +0,0 @@ -use starknet::ContractAddress; - -#[starknet::interface] -trait IERC20 { - fn name(self: @TState) -> felt252; - fn symbol(self: @TState) -> felt252; - fn decimals(self: @TState) -> u8; - fn total_supply(self: @TState) -> u256; - fn balance_of(self: @TState, account: ContractAddress) -> u256; - fn allowance(self: @TState, owner: ContractAddress, spender: 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; - fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool; -} - -trait IERC20CamelOnly { - fn totalSupply(self: @TState) -> u256; - fn balanceOf(self: @TState, account: ContractAddress) -> u256; - fn transferFrom( - ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256 - ) -> bool; -} - -#[starknet::contract] -mod ERC20 { - use dojo_erc::token::erc20_models::{ERC20Allowance, ERC20Balance, ERC20Meta}; - use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - use integer::BoundedInt; - use super::IERC20; - use super::IERC20CamelOnly; - use starknet::ContractAddress; - use starknet::{get_caller_address, get_contract_address}; - use zeroable::Zeroable; - use debug::PrintTrait; - - - #[storage] - struct Storage { - _world: ContractAddress, - } - - #[event] - #[derive(Copy, Drop, starknet::Event)] - enum Event { - Transfer: Transfer, - Approval: Approval, - } - - #[derive(Copy, Drop, starknet::Event)] - struct Transfer { - from: ContractAddress, - to: ContractAddress, - value: u256 - } - - #[derive(Copy, Drop, starknet::Event)] - struct Approval { - owner: ContractAddress, - spender: ContractAddress, - value: u256 - } - - mod Errors { - const APPROVE_FROM_ZERO: felt252 = 'ERC20: approve from 0'; - const APPROVE_TO_ZERO: felt252 = 'ERC20: approve to 0'; - const TRANSFER_FROM_ZERO: felt252 = 'ERC20: transfer from 0'; - const TRANSFER_TO_ZERO: felt252 = 'ERC20: transfer to 0'; - const BURN_FROM_ZERO: felt252 = 'ERC20: burn from 0'; - const MINT_TO_ZERO: felt252 = 'ERC20: mint to 0'; - } - - #[constructor] - fn constructor( - ref self: ContractState, - world: ContractAddress, - name: felt252, - symbol: felt252, - initial_supply: u256, - recipient: ContractAddress - ) { - self._world.write(world); - self.initializer(name, symbol); - self._mint(recipient, initial_supply); - } - - // - // External - // - - #[external(v0)] - impl ERC20Impl of IERC20 { - fn name(self: @ContractState) -> felt252 { - self.get_meta().name - } - - fn symbol(self: @ContractState) -> felt252 { - self.get_meta().symbol - } - - fn decimals(self: @ContractState) -> u8 { - 18 - } - - fn total_supply(self: @ContractState) -> u256 { - self.get_meta().total_supply - } - - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { - self.get_balance(account).amount - } - - fn allowance( - self: @ContractState, owner: ContractAddress, spender: ContractAddress - ) -> u256 { - self.get_allowance(owner, spender).amount - } - - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { - let sender = get_caller_address(); - self._transfer(sender, recipient, amount); - true - } - - fn transfer_from( - ref self: ContractState, - sender: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) -> bool { - let caller = get_caller_address(); - self._spend_allowance(sender, caller, amount); - self._transfer(sender, recipient, amount); - true - } - - fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool { - let owner = get_caller_address(); - self - .set_allowance( - ERC20Allowance { token: get_contract_address(), owner, spender, amount } - ); - true - } - } - - #[external(v0)] - impl ERC20CamelOnlyImpl of IERC20CamelOnly { - fn totalSupply(self: @ContractState) -> u256 { - ERC20Impl::total_supply(self) - } - - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { - ERC20Impl::balance_of(self, account) - } - - fn transferFrom( - ref self: ContractState, - sender: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) -> bool { - ERC20Impl::transfer_from(ref self, sender, recipient, amount) - } - } - - #[external(v0)] - fn increase_allowance( - ref self: ContractState, spender: ContractAddress, added_value: u256 - ) -> bool { - self.update_allowance(get_caller_address(), spender, 0, added_value); - true - } - - #[external(v0)] - fn increaseAllowance( - ref self: ContractState, spender: ContractAddress, addedValue: u256 - ) -> bool { - increase_allowance(ref self, spender, addedValue) - } - - #[external(v0)] - fn decrease_allowance( - ref self: ContractState, spender: ContractAddress, subtracted_value: u256 - ) -> bool { - self.update_allowance(get_caller_address(), spender, subtracted_value, 0); - true - } - - #[external(v0)] - fn decreaseAllowance( - ref self: ContractState, spender: ContractAddress, subtractedValue: u256 - ) -> bool { - decrease_allowance(ref self, spender, subtractedValue) - } - - // - // Internal - // - - #[generate_trait] - impl WorldInteractionsImpl of WorldInteractionsTrait { - fn world(self: @ContractState) -> IWorldDispatcher { - IWorldDispatcher { contract_address: self._world.read() } - } - - fn get_meta(self: @ContractState) -> ERC20Meta { - get!(self.world(), get_contract_address(), ERC20Meta) - } - - // Helper function to update total_supply model - fn update_total_supply(ref self: ContractState, subtract: u256, add: u256) { - let mut meta = self.get_meta(); - // adding and subtracting is fewer steps than if - meta.total_supply = meta.total_supply - subtract; - meta.total_supply = meta.total_supply + add; - set!(self.world(), (meta)); - } - - // Helper function for balance model - fn get_balance(self: @ContractState, account: ContractAddress) -> ERC20Balance { - get!(self.world(), (get_contract_address(), account), ERC20Balance) - } - - fn update_balance( - ref self: ContractState, account: ContractAddress, subtract: u256, add: u256 - ) { - let mut balance: ERC20Balance = self.get_balance(account); - // adding and subtracting is fewer steps than if - balance.amount = balance.amount - subtract; - balance.amount = balance.amount + add; - set!(self.world(), (balance)); - } - - // Helper function for allowance model - fn get_allowance( - self: @ContractState, owner: ContractAddress, spender: ContractAddress, - ) -> ERC20Allowance { - get!(self.world(), (get_contract_address(), owner, spender), ERC20Allowance) - } - - fn update_allowance( - ref self: ContractState, - owner: ContractAddress, - spender: ContractAddress, - subtract: u256, - add: u256 - ) { - let mut allowance = self.get_allowance(owner, spender); - // adding and subtracting is fewer steps than if - allowance.amount = allowance.amount - subtract; - allowance.amount = allowance.amount + add; - self.set_allowance(allowance); - } - - fn set_allowance(ref self: ContractState, allowance: ERC20Allowance) { - assert(!allowance.owner.is_zero(), Errors::APPROVE_FROM_ZERO); - assert(!allowance.spender.is_zero(), Errors::APPROVE_TO_ZERO); - set!(self.world(), (allowance)); - self - .emit_event( - Approval { - owner: allowance.owner, spender: allowance.spender, value: allowance.amount - } - ); - } - - fn emit_event< - S, impl IntoImp: traits::Into, impl SDrop: Drop, impl SCopy: Copy - >( - ref self: ContractState, event: S - ) { - self.emit(event); - emit!(self.world(), event); - } - } - - #[generate_trait] - impl InternalImpl of InternalTrait { - fn initializer(ref self: ContractState, name: felt252, symbol: felt252) { - let meta = ERC20Meta { token: get_contract_address(), name, symbol, total_supply: 0 }; - set!(self.world(), (meta)); - } - - fn _mint(ref self: ContractState, recipient: ContractAddress, amount: u256) { - assert(!recipient.is_zero(), Errors::MINT_TO_ZERO); - self.update_total_supply(0, amount); - self.update_balance(recipient, 0, amount); - self.emit_event(Transfer { from: Zeroable::zero(), to: recipient, value: amount }); - } - - fn _burn(ref self: ContractState, account: ContractAddress, amount: u256) { - assert(!account.is_zero(), Errors::BURN_FROM_ZERO); - self.update_total_supply(amount, 0); - self.update_balance(account, amount, 0); - self.emit_event(Transfer { from: account, to: Zeroable::zero(), value: amount }); - } - - fn _approve( - ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256 - ) { - self - .set_allowance( - ERC20Allowance { token: get_contract_address(), owner, spender, amount } - ); - } - - fn _transfer( - ref self: ContractState, - sender: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) { - assert(!sender.is_zero(), Errors::TRANSFER_FROM_ZERO); - assert(!recipient.is_zero(), Errors::TRANSFER_TO_ZERO); - self.update_balance(sender, amount, 0); - self.update_balance(recipient, 0, amount); - self.emit_event(Transfer { from: sender, to: recipient, value: amount }); - } - - fn _spend_allowance( - ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256 - ) { - let current_allowance = self.get_allowance(owner, spender).amount; - if current_allowance != BoundedInt::max() { - self.update_allowance(owner, spender, amount, 0); - } - } - } -} diff --git a/crates/dojo-erc/src/token/erc20_models.cairo b/crates/dojo-erc/src/token/erc20_models.cairo deleted file mode 100644 index ab68718dc9..0000000000 --- a/crates/dojo-erc/src/token/erc20_models.cairo +++ /dev/null @@ -1,30 +0,0 @@ -use starknet::ContractAddress; - -#[derive(Model, Copy, Drop, Serde)] -struct ERC20Balance { - #[key] - token: ContractAddress, - #[key] - account: ContractAddress, - amount: u256, -} - -#[derive(Model, Copy, Drop, Serde)] -struct ERC20Allowance { - #[key] - token: ContractAddress, - #[key] - owner: ContractAddress, - #[key] - spender: ContractAddress, - amount: u256, -} - -#[derive(Model, Copy, Drop, Serde)] -struct ERC20Meta { - #[key] - token: ContractAddress, - name: felt252, - symbol: felt252, - total_supply: u256, -} diff --git a/crates/dojo-erc/src/token/erc721.cairo b/crates/dojo-erc/src/token/erc721.cairo deleted file mode 100644 index 15b96462ac..0000000000 --- a/crates/dojo-erc/src/token/erc721.cairo +++ /dev/null @@ -1,5 +0,0 @@ -mod erc721; -mod models; -mod interface; - -use erc721::ERC721; diff --git a/crates/dojo-erc/src/token/erc721/erc721.cairo b/crates/dojo-erc/src/token/erc721/erc721.cairo deleted file mode 100644 index ffd7915d82..0000000000 --- a/crates/dojo-erc/src/token/erc721/erc721.cairo +++ /dev/null @@ -1,443 +0,0 @@ -#[starknet::contract] -mod ERC721 { - use dojo_erc::token::erc721::models::{ - ERC721Meta, ERC721OperatorApproval, ERC721Owner, ERC721Balance, ERC721TokenApproval - }; - use dojo_erc::token::erc721::interface; - use dojo_erc::token::erc721::interface::{IERC721, IERC721CamelOnly}; - use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - use integer::BoundedInt; - use starknet::ContractAddress; - use starknet::{get_caller_address, get_contract_address}; - use zeroable::Zeroable; - use debug::PrintTrait; - - - #[storage] - struct Storage { - _world: ContractAddress, - } - - #[event] - #[derive(Copy, Drop, starknet::Event)] - enum Event { - Transfer: Transfer, - Approval: Approval, - ApprovalForAll: ApprovalForAll - } - - #[derive(Copy, Drop, starknet::Event)] - struct Transfer { - from: ContractAddress, - to: ContractAddress, - token_id: u256 - } - - #[derive(Copy, Drop, starknet::Event)] - struct Approval { - owner: ContractAddress, - approved: ContractAddress, - token_id: u256 - } - - #[derive(Copy, Drop, starknet::Event)] - struct ApprovalForAll { - owner: ContractAddress, - operator: ContractAddress, - approved: bool - } - - mod Errors { - const INVALID_TOKEN_ID: felt252 = 'ERC721: invalid token ID'; - const INVALID_ACCOUNT: felt252 = 'ERC721: invalid account'; - const UNAUTHORIZED: felt252 = 'ERC721: unauthorized caller'; - const APPROVAL_TO_OWNER: felt252 = 'ERC721: approval to owner'; - const SELF_APPROVAL: felt252 = 'ERC721: self approval'; - const INVALID_RECEIVER: felt252 = 'ERC721: invalid receiver'; - const ALREADY_MINTED: felt252 = 'ERC721: token already minted'; - const WRONG_SENDER: felt252 = 'ERC721: wrong sender'; - const SAFE_MINT_FAILED: felt252 = 'ERC721: safe mint failed'; - const SAFE_TRANSFER_FAILED: felt252 = 'ERC721: safe transfer failed'; - } - - #[constructor] - fn constructor( - ref self: ContractState, - world: ContractAddress, - name: felt252, - symbol: felt252, - base_uri: felt252, - recipient: ContractAddress, - token_id: u256 - ) { - self._world.write(world); - self.initializer(name, symbol, base_uri); - self._mint(recipient, token_id); - } - - // - // External - // - - // #[external(v0)] - // impl SRC5Impl of ISRC5 { - // fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - // let unsafe_state = src5::SRC5::unsafe_new_contract_state(); - // src5::SRC5::SRC5Impl::supports_interface(@unsafe_state, interface_id) - // } - // } - - // #[external(v0)] - // impl SRC5CamelImpl of ISRC5Camel { - // fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - // let unsafe_state = src5::SRC5::unsafe_new_contract_state(); - // src5::SRC5::SRC5CamelImpl::supportsInterface(@unsafe_state, interfaceId) - // } - // } - - #[external(v0)] - impl ERC721MetadataImpl of interface::IERC721Metadata { - fn name(self: @ContractState) -> felt252 { - self.get_meta().name - } - - fn symbol(self: @ContractState) -> felt252 { - self.get_meta().symbol - } - - fn token_uri(self: @ContractState, token_id: u256) -> felt252 { - assert(self._exists(token_id), Errors::INVALID_TOKEN_ID); - // TODO : concat with id - self.get_uri(token_id) - } - } - - #[external(v0)] - impl ERC721MetadataCamelOnlyImpl of interface::IERC721MetadataCamelOnly { - fn tokenURI(self: @ContractState, tokenId: u256) -> felt252 { - assert(self._exists(tokenId), Errors::INVALID_TOKEN_ID); - self.get_uri(tokenId) - } - } - - #[external(v0)] - impl ERC721Impl of interface::IERC721 { - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { - assert(account.is_non_zero(), Errors::INVALID_ACCOUNT); - self.get_balance(account).amount - } - - fn owner_of(self: @ContractState, token_id: u256) -> ContractAddress { - self._owner_of(token_id) - } - - fn get_approved(self: @ContractState, token_id: u256) -> ContractAddress { - assert(self._exists(token_id), Errors::INVALID_TOKEN_ID); - self.get_token_approval(token_id).address - } - - fn is_approved_for_all( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> bool { - self.get_operator_approval(owner, operator).approved - } - - fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) { - let owner = self._owner_of(token_id); - - let caller = get_caller_address(); - assert( - owner == caller || ERC721Impl::is_approved_for_all(@self, owner, caller), - Errors::UNAUTHORIZED - ); - self._approve(to, token_id); - } - - fn set_approval_for_all( - ref self: ContractState, operator: ContractAddress, approved: bool - ) { - self._set_approval_for_all(get_caller_address(), operator, approved) - } - - fn transfer_from( - ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256 - ) { - assert( - self._is_approved_or_owner(get_caller_address(), token_id), Errors::UNAUTHORIZED - ); - self._transfer(from, to, token_id); - } - - fn safe_transfer_from( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - token_id: u256, - data: Span - ) { - assert( - self._is_approved_or_owner(get_caller_address(), token_id), Errors::UNAUTHORIZED - ); - self._safe_transfer(from, to, token_id, data); - } - } - - #[external(v0)] - impl ERC721CamelOnlyImpl of interface::IERC721CamelOnly { - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { - ERC721Impl::balance_of(self, account) - } - - fn ownerOf(self: @ContractState, tokenId: u256) -> ContractAddress { - ERC721Impl::owner_of(self, tokenId) - } - - fn getApproved(self: @ContractState, tokenId: u256) -> ContractAddress { - ERC721Impl::get_approved(self, tokenId) - } - - fn isApprovedForAll( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> bool { - ERC721Impl::is_approved_for_all(self, owner, operator) - } - - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) { - ERC721Impl::set_approval_for_all(ref self, operator, approved) - } - - fn transferFrom( - ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256 - ) { - ERC721Impl::transfer_from(ref self, from, to, tokenId) - } - - fn safeTransferFrom( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - tokenId: u256, - data: Span - ) { - ERC721Impl::safe_transfer_from(ref self, from, to, tokenId, data) - } - } - - // - // Internal - // - - #[generate_trait] - impl WorldInteractionsImpl of WorldInteractionsTrait { - fn world(self: @ContractState) -> IWorldDispatcher { - IWorldDispatcher { contract_address: self._world.read() } - } - - fn get_meta(self: @ContractState) -> ERC721Meta { - get!(self.world(), get_contract_address(), ERC721Meta) - } - - fn get_uri(self: @ContractState, token_id: u256) -> felt252 { - // TODO : concat with id when we have string type - self.get_meta().base_uri - } - - fn get_balance(self: @ContractState, account: ContractAddress) -> ERC721Balance { - get!(self.world(), (get_contract_address(), account), ERC721Balance) - } - - fn get_owner_of(self: @ContractState, token_id: u256) -> ERC721Owner { - get!(self.world(), (get_contract_address(), token_id), ERC721Owner) - } - - fn get_token_approval(self: @ContractState, token_id: u256) -> ERC721TokenApproval { - get!(self.world(), (get_contract_address(), token_id), ERC721TokenApproval) - } - - fn get_operator_approval( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> ERC721OperatorApproval { - get!(self.world(), (get_contract_address(), owner, operator), ERC721OperatorApproval) - } - - fn set_token_approval( - ref self: ContractState, - owner: ContractAddress, - to: ContractAddress, - token_id: u256, - emit: bool - ) { - set!( - self.world(), - ERC721TokenApproval { token: get_contract_address(), token_id, address: to, } - ); - if emit { - self.emit_event(Approval { owner, approved: to, token_id }); - } - } - - fn set_operator_approval( - ref self: ContractState, - owner: ContractAddress, - operator: ContractAddress, - approved: bool - ) { - set!( - self.world(), - ERC721OperatorApproval { token: get_contract_address(), owner, operator, approved } - ); - self.emit_event(ApprovalForAll { owner, operator, approved }); - } - - fn set_balance(ref self: ContractState, account: ContractAddress, amount: u256) { - set!(self.world(), ERC721Balance { token: get_contract_address(), account, amount }); - } - - fn set_owner(ref self: ContractState, token_id: u256, address: ContractAddress) { - set!(self.world(), ERC721Owner { token: get_contract_address(), token_id, address }); - } - - fn emit_event< - S, impl IntoImp: traits::Into, impl SDrop: Drop, impl SCopy: Copy - >( - ref self: ContractState, event: S - ) { - self.emit(event); - emit!(self.world(), event); - } - } - - #[generate_trait] - impl InternalImpl of InternalTrait { - fn initializer(ref self: ContractState, name: felt252, symbol: felt252, base_uri: felt252) { - let meta = ERC721Meta { token: get_contract_address(), name, symbol, base_uri }; - set!(self.world(), (meta)); - // let mut unsafe_state = src5::SRC5::unsafe_new_contract_state(); - // src5::SRC5::InternalImpl::register_interface(ref unsafe_state, interface::IERC721_ID); - // src5::SRC5::InternalImpl::register_interface( - // ref unsafe_state, interface::IERC721_METADATA_ID - // ); - } - - fn _owner_of(self: @ContractState, token_id: u256) -> ContractAddress { - let owner = self.get_owner_of(token_id).address; - match owner.is_zero() { - bool::False(()) => owner, - bool::True(()) => panic_with_felt252(Errors::INVALID_TOKEN_ID) - } - } - - fn _exists(self: @ContractState, token_id: u256) -> bool { - let owner = self.get_owner_of(token_id).address; - owner.is_non_zero() - } - - fn _is_approved_or_owner( - self: @ContractState, spender: ContractAddress, token_id: u256 - ) -> bool { - let owner = self._owner_of(token_id); - let is_approved_for_all = ERC721Impl::is_approved_for_all(self, owner, spender); - owner == spender - || is_approved_for_all - || spender == ERC721Impl::get_approved(self, token_id) - } - - fn _approve(ref self: ContractState, to: ContractAddress, token_id: u256) { - let owner = self._owner_of(token_id); - assert(owner != to, Errors::APPROVAL_TO_OWNER); - - self.set_token_approval(owner, to, token_id, true); - } - - fn _set_approval_for_all( - ref self: ContractState, - owner: ContractAddress, - operator: ContractAddress, - approved: bool - ) { - assert(owner != operator, Errors::SELF_APPROVAL); - self.set_operator_approval(owner, operator, approved); - } - - fn _mint(ref self: ContractState, to: ContractAddress, token_id: u256) { - assert(!to.is_zero(), Errors::INVALID_RECEIVER); - assert(!self._exists(token_id), Errors::ALREADY_MINTED); - - self.set_balance(to, self.get_balance(to).amount + 1); - self.set_owner(token_id, to); - - self.emit_event(Transfer { from: Zeroable::zero(), to, token_id }); - } - - fn _transfer( - ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256 - ) { - assert(!to.is_zero(), Errors::INVALID_RECEIVER); - let owner = self._owner_of(token_id); - assert(from == owner, Errors::WRONG_SENDER); - - // Implicit clear approvals, no need to emit an event - self.set_token_approval(owner, Zeroable::zero(), token_id, false); - - self.set_balance(from, self.get_balance(from).amount - 1); - self.set_balance(to, self.get_balance(to).amount + 1); - self.set_owner(token_id, to); - - self.emit_event(Transfer { from, to, token_id }); - } - - fn _burn(ref self: ContractState, token_id: u256) { - let owner = self._owner_of(token_id); - - // Implicit clear approvals, no need to emit an event - self.set_token_approval(owner, Zeroable::zero(), token_id, false); - - self.set_balance(owner, self.get_balance(owner).amount - 1); - self.set_owner(token_id, Zeroable::zero()); - - self.emit_event(Transfer { from: owner, to: Zeroable::zero(), token_id }); - } - - fn _safe_mint( - ref self: ContractState, to: ContractAddress, token_id: u256, data: Span - ) { - self._mint(to, token_id); - // assert( - // _check_on_erc721_received(Zeroable::zero(), to, token_id, data), - // Errors::SAFE_MINT_FAILED - // ); - } - - fn _safe_transfer( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - token_id: u256, - data: Span - ) { - self._transfer(from, to, token_id); - // assert( - // _check_on_erc721_received(from, to, token_id, data), Errors::SAFE_TRANSFER_FAILED - // ); - } - // fn _set_token_uri(ref self: ContractState, token_id: u256, token_uri: felt252) { - // assert(self._exists(token_id), Errors::INVALID_TOKEN_ID); - // self._token_uri.write(token_id, token_uri) - // } - } - -//#[internal] -// fn _check_on_erc721_received( -// from: ContractAddress, to: ContractAddress, token_id: u256, data: Span -// ) -> bool { -// if (DualCaseSRC5 { contract_address: to } -// .supports_interface(interface::IERC721_RECEIVER_ID)) { -// DualCaseERC721Receiver { contract_address: to } -// .on_erc721_received( -// get_caller_address(), from, token_id, data -// ) == interface::IERC721_RECEIVER_ID -// } else { -// DualCaseSRC5 { contract_address: to }.supports_interface(account::interface::ISRC6_ID) -// } -// } -} diff --git a/crates/dojo-erc/src/token/erc721/interface.cairo b/crates/dojo-erc/src/token/erc721/interface.cairo deleted file mode 100644 index 730ad2e027..0000000000 --- a/crates/dojo-erc/src/token/erc721/interface.cairo +++ /dev/null @@ -1,60 +0,0 @@ -use starknet::ContractAddress; - -const IERC721_ID: felt252 = 0x33eb2f84c309543403fd69f0d0f363781ef06ef6faeb0131ff16ea3175bd943; -const IERC721_METADATA_ID: felt252 = - 0x6069a70848f907fa57668ba1875164eb4dcee693952468581406d131081bbd; -const IERC721_RECEIVER_ID: felt252 = - 0x3a0dff5f70d80458ad14ae37bb182a728e3c8cdda0402a5daa86620bdf910bc; - -#[starknet::interface] -trait IERC721 { - fn balance_of(self: @TState, account: ContractAddress) -> u256; - fn owner_of(self: @TState, token_id: u256) -> ContractAddress; - fn transfer_from(ref self: TState, from: ContractAddress, to: ContractAddress, token_id: u256); - fn safe_transfer_from( - ref self: TState, - from: ContractAddress, - to: ContractAddress, - token_id: u256, - data: Span - ); - fn approve(ref self: TState, to: ContractAddress, token_id: u256); - fn set_approval_for_all(ref self: TState, operator: ContractAddress, approved: bool); - fn get_approved(self: @TState, token_id: u256) -> ContractAddress; - fn is_approved_for_all( - self: @TState, owner: ContractAddress, operator: ContractAddress - ) -> bool; -} - -#[starknet::interface] -trait IERC721CamelOnly { - fn balanceOf(self: @TState, account: ContractAddress) -> u256; - fn ownerOf(self: @TState, tokenId: u256) -> ContractAddress; - fn transferFrom(ref self: TState, from: ContractAddress, to: ContractAddress, tokenId: u256); - fn safeTransferFrom( - ref self: TState, - from: ContractAddress, - to: ContractAddress, - tokenId: u256, - data: Span - ); - fn setApprovalForAll(ref self: TState, operator: ContractAddress, approved: bool); - fn getApproved(self: @TState, tokenId: u256) -> ContractAddress; - fn isApprovedForAll(self: @TState, owner: ContractAddress, operator: ContractAddress) -> bool; -} - -// -// IERC721Metadata -// - -#[starknet::interface] -trait IERC721Metadata { - fn name(self: @TState) -> felt252; - fn symbol(self: @TState) -> felt252; - fn token_uri(self: @TState, token_id: u256) -> felt252; -} - -#[starknet::interface] -trait IERC721MetadataCamelOnly { - fn tokenURI(self: @TState, tokenId: u256) -> felt252; -} diff --git a/crates/dojo-erc/src/token/erc721/models.cairo b/crates/dojo-erc/src/token/erc721/models.cairo deleted file mode 100644 index 1bc4bcadd6..0000000000 --- a/crates/dojo-erc/src/token/erc721/models.cairo +++ /dev/null @@ -1,48 +0,0 @@ -use starknet::ContractAddress; - -#[derive(Model, Copy, Drop, Serde)] -struct ERC721Meta { - #[key] - token: ContractAddress, - name: felt252, - symbol: felt252, - base_uri: felt252, -} - -#[derive(Model, Copy, Drop, Serde)] -struct ERC721OperatorApproval { - #[key] - token: ContractAddress, - #[key] - owner: ContractAddress, - #[key] - operator: ContractAddress, - approved: bool -} - -#[derive(Model, Copy, Drop, Serde)] -struct ERC721Owner { - #[key] - token: ContractAddress, - #[key] - token_id: u256, - address: ContractAddress -} - -#[derive(Model, Copy, Drop, Serde)] -struct ERC721Balance { - #[key] - token: ContractAddress, - #[key] - account: ContractAddress, - amount: u256, -} - -#[derive(Model, Copy, Drop, Serde)] -struct ERC721TokenApproval { - #[key] - token: ContractAddress, - #[key] - token_id: u256, - address: ContractAddress, -} \ No newline at end of file diff --git a/crates/dojo-physics/.gitignore b/crates/dojo-physics/.gitignore deleted file mode 100644 index 1de565933b..0000000000 --- a/crates/dojo-physics/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target \ No newline at end of file diff --git a/crates/dojo-physics/Scarb.toml b/crates/dojo-physics/Scarb.toml deleted file mode 100644 index c23523ebaf..0000000000 --- a/crates/dojo-physics/Scarb.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -cairo-version = "2.0.0-rc4" -description = "Implementations of a physics library for the Dojo framework" -name = "dojo_physics" -version = "0.3.11" - -[dependencies] -cubit = { git = "https://github.com/influenceth/cubit" } -dojo = { path = "../dojo-core" } - -[[target.dojo]] diff --git a/crates/dojo-physics/examples/projectile/Scarb.toml b/crates/dojo-physics/examples/projectile/Scarb.toml deleted file mode 100644 index c54bfcb9ee..0000000000 --- a/crates/dojo-physics/examples/projectile/Scarb.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "projectile" -version = "0.3.11" - -[dependencies] -cubit = { git = "https://github.com/influenceth/cubit" } -dojo_physics = { path = "../.." } diff --git a/crates/dojo-physics/examples/projectile/cairo_project.toml b/crates/dojo-physics/examples/projectile/cairo_project.toml deleted file mode 100644 index 5ec5b278ba..0000000000 --- a/crates/dojo-physics/examples/projectile/cairo_project.toml +++ /dev/null @@ -1,3 +0,0 @@ -[crate_roots] -dojo_physics = "../../src" -projectile = "src" diff --git a/crates/dojo-physics/examples/projectile/src/lib.cairo b/crates/dojo-physics/examples/projectile/src/lib.cairo deleted file mode 100644 index ee069f413f..0000000000 --- a/crates/dojo-physics/examples/projectile/src/lib.cairo +++ /dev/null @@ -1 +0,0 @@ -mod projectile; \ No newline at end of file diff --git a/crates/dojo-physics/examples/projectile/src/projectile.cairo b/crates/dojo-physics/examples/projectile/src/projectile.cairo deleted file mode 100644 index f6be9b8101..0000000000 --- a/crates/dojo-physics/examples/projectile/src/projectile.cairo +++ /dev/null @@ -1,245 +0,0 @@ -use core::option::OptionTrait; -use array::ArrayTrait; -use debug::PrintTrait; -use array::ArrayTCloneImpl; -use array::SpanTrait; -use clone::Clone; -use traits::PartialOrd; - -use cubit::test::helpers::assert_precise; -use cubit::types::fixed::{Fixed, FixedPartialOrd, FixedTrait, ONE_u128}; -use cubit::math::trig; - -use dojo_physics::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(FixedPartialOrd::le(x_0, x_max), 'need x_0 <= x_max'); - assert(FixedPartialOrd::ge(x_0, x_min), 'need x_0 >= x_min'); - assert(FixedPartialOrd::le(y_0, y_max), 'need y_0 <= y_max'); - assert(FixedPartialOrd::ge(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 -} - -#[test] -#[available_gas(2000000)] -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] -#[available_gas(20000000)] -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] -#[available_gas(20000000)] -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] -#[available_gas(2000000)] -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] -#[available_gas(2000000)] -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/crates/dojo-physics/src/lib.cairo b/crates/dojo-physics/src/lib.cairo deleted file mode 100644 index f26f218845..0000000000 --- a/crates/dojo-physics/src/lib.cairo +++ /dev/null @@ -1 +0,0 @@ -mod vec2; diff --git a/crates/dojo-physics/src/vec2.cairo b/crates/dojo-physics/src/vec2.cairo deleted file mode 100644 index edf4501a10..0000000000 --- a/crates/dojo-physics/src/vec2.cairo +++ /dev/null @@ -1,261 +0,0 @@ -use cubit::types::fixed::{Fixed, FixedTrait, ONE_u128}; - -struct Vec2 { - x: T, - y: T -} - -impl Vec2Copy> of Copy>; -impl Vec2Drop> of Drop>; - -trait Vec2Trait { - // Constructors - fn new(x: T, y: T) -> Vec2; - fn splat(self: T) -> Vec2; - // Masks - fn select(mask: Vec2, if_true: Vec2, if_false: Vec2) -> Vec2; - // Math - fn dot, impl TAdd: Add>(self: Vec2, rhs: Vec2) -> T; - fn dot_into_vec, impl TAdd: Add>(self: Vec2, rhs: Vec2) -> Vec2; - // Swizzles - fn xy(self: Vec2) -> Vec2; - fn xx(self: Vec2) -> Vec2; - fn yx(self: Vec2) -> Vec2; - fn yy(self: Vec2) -> Vec2; -} - -impl Vec2Impl, impl TDrop: Drop> of Vec2Trait { - // Constructors - - /// Creates a new vector. - #[inline(always)] - fn new(x: T, y: T) -> Vec2 { - Vec2 { x: x, y: y } - } - /// Creates a vector with all elements set to `v`. - #[inline(always)] - fn splat(self: T) -> Vec2 { - Vec2 { x: self, y: self } - } - - // Masks - - /// Creates a vector from the elements in `if_true` and `if_false`, - /// selecting which to use for each element of `self`. - /// - /// A true element in the mask uses the corresponding element from - /// `if_true`, and false uses the element from `if_false`. - #[inline(always)] - fn select(mask: Vec2, if_true: Vec2, if_false: Vec2) -> Vec2 { - Vec2 { - x: if mask.x { - if_true.x - } else { - if_false.x - }, - y: if mask.y { - if_true.y - } else { - if_false.y - }, - } - } - - // Math - - /// Computes the dot product of `self` and `rhs` . - // #[inline(always)] is not allowed for functions with impl generic parameters. - fn dot, impl TAdd: Add>(self: Vec2, rhs: Vec2) -> T { - (self.x * rhs.x) + (self.y * rhs.y) - } - /// Returns a vector where every component is the dot product - /// of `self` and `rhs`. - fn dot_into_vec, impl TAdd: Add>(self: Vec2, rhs: Vec2) -> Vec2 { - Vec2Trait::splat(Vec2Trait::dot(self, rhs)) - } - - // Swizzles - /// Vec2 -> Vec2 - #[inline(always)] - fn xx(self: Vec2) -> Vec2 { - Vec2 { x: self.x, y: self.x, } - } - - #[inline(always)] - fn xy(self: Vec2) -> Vec2 { - Vec2 { x: self.x, y: self.y, } - } - - #[inline(always)] - fn yx(self: Vec2) -> Vec2 { - Vec2 { x: self.y, y: self.x, } - } - - #[inline(always)] - fn yy(self: Vec2) -> Vec2 { - Vec2 { x: self.y, y: self.y, } - } -} - -#[test] -#[available_gas(2000000)] -fn test_new() { - let var1_pos = FixedTrait::new(ONE_u128, false); - let var2_neg = FixedTrait::new(2 * ONE_u128, true); - - // with Fixed type - let vec2 = Vec2Trait::new(var1_pos, var2_neg); - assert(vec2.x.mag == ONE_u128, 'invalid x.mag'); - assert(vec2.x.sign == false, 'invalid x.sign'); - assert(vec2.y.mag == 2 * ONE_u128, 'invalid y.mag'); - assert(vec2.y.sign == true, 'invalid y.sign'); - - // with bool - let bvec2tf = Vec2Trait::new(true, false); - assert(bvec2tf.x == true, 'invalid new x'); - assert(bvec2tf.y == false, 'invalid new y'); -} - -#[test] -#[available_gas(2000000)] -fn test_splat() { - let var = FixedTrait::new(ONE_u128, false); - - // with Fixed type - let vec2 = Vec2Trait::splat(var); - assert(vec2.x.mag == ONE_u128, 'invalid x.mag'); - assert(vec2.x.sign == false, 'invalid x.sign'); - assert(vec2.y.mag == ONE_u128, 'invalid y.mag'); - assert(vec2.y.sign == false, 'invalid y.sign'); - - // with bool - let bvec2tt = Vec2Trait::splat(true); - assert(bvec2tt.x == true, 'invalid x'); - assert(bvec2tt.y == true, 'invalid y'); -} - -#[test] -#[available_gas(2000000)] -fn test_select() { - let var1_pos = FixedTrait::new(ONE_u128, false); - let var2_neg = FixedTrait::new(2 * ONE_u128, true); - let var3_neg = FixedTrait::new(3 * ONE_u128, true); - let var4_pos = FixedTrait::new(4 * ONE_u128, false); - - let vec2a = Vec2Trait::new(var1_pos, var2_neg); - let vec2b = Vec2Trait::new(var3_neg, var4_pos); - - let mask = Vec2Trait::new(true, false); - let vec2 = Vec2Trait::select(mask, vec2a, vec2b); - assert(vec2.x.mag == ONE_u128, 'invalid x.mag'); - assert(vec2.x.sign == false, 'invalid x.sign'); - assert(vec2.y.mag == 4 * ONE_u128, 'invalid y.mag'); - assert(vec2.y.sign == false, 'invalid y.sign'); - - let mask = Vec2Trait::new(false, true); - let vec2 = Vec2Trait::select(mask, vec2a, vec2b); - assert(vec2.x.mag == 3 * ONE_u128, 'invalid x.mag'); - assert(vec2.x.sign == true, 'invalid x.sign'); - assert(vec2.y.mag == 2 * ONE_u128, 'invalid y.mag'); - assert(vec2.y.sign == true, 'invalid y.sign'); -} - -#[test] -#[available_gas(2000000)] -fn test_dot() { - let var1_pos = FixedTrait::new(ONE_u128, false); - let var2_neg = FixedTrait::new(2 * ONE_u128, true); - let var3_neg = FixedTrait::new(3 * ONE_u128, true); - let var4_pos = FixedTrait::new(4 * ONE_u128, false); - - let vec2a = Vec2Trait::new(var1_pos, var2_neg); - let vec2b = Vec2Trait::new(var3_neg, var4_pos); - - let a_dot_b = vec2a.dot(vec2b); - assert(a_dot_b.mag == 11 * ONE_u128, 'invalid mag'); - assert(a_dot_b.sign == true, 'invalid sign'); - - let a_dot_b = Vec2Trait::dot(vec2a, vec2b); // alt syntax - assert(a_dot_b.mag == 11 * ONE_u128, 'invalid mag'); - assert(a_dot_b.sign == true, 'invalid sign'); -} - -#[test] -#[available_gas(2000000)] -fn test_dot_into_vec() { - let var1_pos = FixedTrait::new(ONE_u128, false); - let var2_neg = FixedTrait::new(2 * ONE_u128, true); - let var3_neg = FixedTrait::new(3 * ONE_u128, true); - let var4_pos = FixedTrait::new(4 * ONE_u128, false); - - let vec2a = Vec2Trait::new(var1_pos, var2_neg); - let vec2b = Vec2Trait::new(var3_neg, var4_pos); - - let vec2 = vec2a.dot_into_vec(vec2b); - assert(vec2.x.mag == 11 * ONE_u128, 'invalid x.mag'); - assert(vec2.x.sign == true, 'invalid x.sign'); - assert(vec2.y.mag == 11 * ONE_u128, 'invalid y.mag'); - assert(vec2.y.sign == true, 'invalid y.sign'); - - let vec2 = Vec2Trait::dot_into_vec(vec2a, vec2b); // alt syntax - assert(vec2.x.mag == 11 * ONE_u128, 'invalid x.mag'); - assert(vec2.x.sign == true, 'invalid x.sign'); - assert(vec2.y.mag == 11 * ONE_u128, 'invalid y.mag'); - assert(vec2.y.sign == true, 'invalid y.sign'); -} - -#[test] -#[available_gas(2000000)] -fn test_xx() { - let var1_pos = FixedTrait::new(ONE_u128, false); - let var2_neg = FixedTrait::new(2 * ONE_u128, true); - let vec2 = Vec2Trait::new(var1_pos, var2_neg); - - let vec2xx = vec2.xx(); - assert(vec2xx.x.mag == ONE_u128, 'invalid x.mag'); - assert(vec2xx.x.sign == false, 'invalid x.sign'); - assert(vec2xx.y.mag == ONE_u128, 'invalid y.mag'); - assert(vec2xx.y.sign == false, 'invalid y.sign'); -} - -#[test] -#[available_gas(2000000)] -fn test_xy() { - let var1_pos = FixedTrait::new(ONE_u128, false); - let var2_neg = FixedTrait::new(2 * ONE_u128, true); - let vec2 = Vec2Trait::new(var1_pos, var2_neg); - - let vec2xy = vec2.xy(); - assert(vec2xy.x.mag == ONE_u128, 'invalid x.mag'); - assert(vec2xy.x.sign == false, 'invalid x.sign'); - assert(vec2xy.y.mag == 2 * ONE_u128, 'invalid xy.mag'); - assert(vec2xy.y.sign == true, 'invalid y.sign'); -} - -#[test] -#[available_gas(2000000)] -fn test_yx() { - let var1_pos = FixedTrait::new(ONE_u128, false); - let var2_neg = FixedTrait::new(2 * ONE_u128, true); - let vec2 = Vec2Trait::new(var1_pos, var2_neg); - - let vec2yx = vec2.yx(); - assert(vec2yx.x.mag == 2 * ONE_u128, 'invalid x.mag'); - assert(vec2yx.x.sign == true, 'invalid x.sign'); - assert(vec2yx.y.mag == ONE_u128, 'invalid y.mag'); - assert(vec2yx.y.sign == false, 'invalid y.sign'); -} - -#[test] -#[available_gas(2000000)] -fn test_yy() { - let var1_pos = FixedTrait::new(ONE_u128, false); - let var2_neg = FixedTrait::new(2 * ONE_u128, true); - let vec2 = Vec2Trait::new(var1_pos, var2_neg); - - let vec2yy = vec2.yy(); - assert(vec2yy.x.mag == 2 * ONE_u128, 'invalid x.mag'); - assert(vec2yy.x.sign == true, 'invalid x.sign'); - assert(vec2yy.y.mag == 2 * ONE_u128, 'invalid y.mag'); - assert(vec2yy.y.sign == true, 'invalid y.sign'); -} diff --git a/crates/dojo-primitives/Scarb.lock b/crates/dojo-primitives/Scarb.lock deleted file mode 100644 index 193cddd288..0000000000 --- a/crates/dojo-primitives/Scarb.lock +++ /dev/null @@ -1,21 +0,0 @@ -# Code generated by scarb DO NOT EDIT. -version = 1 - -[[package]] -name = "dojo" -version = "0.3.11" -dependencies = [ - "dojo_plugin", -] - -[[package]] -name = "dojo_plugin" -version = "0.3.11" -source = "git+https://github.com/dojoengine/dojo?tag=v0.3.11#adab82da604669393bf5391439ed4ab1825923d1" - -[[package]] -name = "dojo_primitives" -version = "0.3.11" -dependencies = [ - "dojo", -] diff --git a/crates/dojo-primitives/Scarb.toml b/crates/dojo-primitives/Scarb.toml deleted file mode 100644 index b25e0045fb..0000000000 --- a/crates/dojo-primitives/Scarb.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -cairo-version = "2.3.1" -description = "Implementations of common primitives for the Dojo games" -name = "dojo_primitives" -version = "0.3.11" - -[lib] - -[dependencies] -dojo = { path = "../dojo-core" } - -[[target.dojo]] diff --git a/crates/dojo-primitives/src/commit_reveal.cairo b/crates/dojo-primitives/src/commit_reveal.cairo deleted file mode 100644 index eda95a130c..0000000000 --- a/crates/dojo-primitives/src/commit_reveal.cairo +++ /dev/null @@ -1,31 +0,0 @@ -use serde::Serde; -use poseidon::poseidon_hash_span; - -#[derive(Copy, Drop, Default, Serde, Introspect)] -struct Commitment { - hash: felt252 -} - -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 { - fn new() -> Commitment { - Commitment { hash: 0 } - } - - fn commit(ref self: Commitment, hash: felt252) { - assert(hash.is_non_zero(), 'can not commit zero'); - self.hash = hash; - } - - fn reveal, impl TDrop: Drop>(self: @Commitment, reveal: T) -> bool { - let mut serialized = array![]; - reveal.serialize(ref serialized); - let hash = poseidon_hash_span(serialized.span()); - return hash == *self.hash; - } -} diff --git a/crates/dojo-primitives/src/commit_reveal_test.cairo b/crates/dojo-primitives/src/commit_reveal_test.cairo deleted file mode 100644 index 44a6044f74..0000000000 --- a/crates/dojo-primitives/src/commit_reveal_test.cairo +++ /dev/null @@ -1,15 +0,0 @@ -use serde::Serde; -use poseidon::poseidon_hash_span; -use dojo_primitives::commit_reveal::{Commitment, CommitmentTrait}; - -#[test] -#[available_gas(1000000)] -fn test_commit_reveal() { - let mut commitment = CommitmentTrait::new(); - - let value = array!['ohayo'].span(); - let hash = poseidon_hash_span(value); - commitment.commit(hash); - let valid = commitment.reveal('ohayo'); - assert(valid, 'invalid reveal for commitment') -} diff --git a/crates/dojo-primitives/src/lib.cairo b/crates/dojo-primitives/src/lib.cairo deleted file mode 100644 index 67120026d5..0000000000 --- a/crates/dojo-primitives/src/lib.cairo +++ /dev/null @@ -1,4 +0,0 @@ -mod commit_reveal; - -#[cfg(test)] -mod commit_reveal_test; diff --git a/scripts/cairo_test.sh b/scripts/cairo_test.sh index 70b241064a..b4f57ad916 100755 --- a/scripts/cairo_test.sh +++ b/scripts/cairo_test.sh @@ -2,8 +2,4 @@ set -euxo pipefail cargo run -r --bin sozo -- --manifest-path crates/dojo-core/Scarb.toml test $@ -# cargo run --bin sozo -- test crates/dojo-physics -cargo run -r --bin sozo -- --manifest-path crates/dojo-erc/Scarb.toml test $@ -cargo run -r --bin sozo -- --manifest-path crates/dojo-defi/Scarb.toml test $@ -cargo run -r --bin sozo -- --manifest-path crates/dojo-primitives/Scarb.toml test $@ cargo run -r --bin sozo -- --manifest-path examples/spawn-and-move/Scarb.toml test $@