From bdf4c57eda6b98e227a27d22c6d7a426719fbace Mon Sep 17 00:00:00 2001 From: Tijesunimi004 Date: Mon, 30 Mar 2026 14:20:11 +0100 Subject: [PATCH 1/3] feat(commitment_marketplace): cannot-buy-own-listing-additional-edge-cases-and-fuzz-inputs --- Cargo.lock | 1 + contracts/commitment_marketplace/Cargo.toml | 1 + contracts/commitment_marketplace/src/lib.rs | 47 +++++++++++++++---- contracts/commitment_marketplace/src/tests.rs | 47 +++++++++++++++++++ 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc592ba7..e0397e72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,6 +163,7 @@ dependencies = [ name = "commitment-marketplace" version = "0.1.0" dependencies = [ + "shared_utils", "soroban-sdk", ] diff --git a/contracts/commitment_marketplace/Cargo.toml b/contracts/commitment_marketplace/Cargo.toml index 5f9a3f21..3918f37e 100644 --- a/contracts/commitment_marketplace/Cargo.toml +++ b/contracts/commitment_marketplace/Cargo.toml @@ -8,6 +8,7 @@ crate-type = ["cdylib"] [dependencies] soroban-sdk = "21.0.0" +shared_utils = { path = "../shared_utils" } [dev-dependencies] soroban-sdk = { version = "21.0.0", features = ["testutils"] } diff --git a/contracts/commitment_marketplace/src/lib.rs b/contracts/commitment_marketplace/src/lib.rs index dc9a4590..d8caefc8 100644 --- a/contracts/commitment_marketplace/src/lib.rs +++ b/contracts/commitment_marketplace/src/lib.rs @@ -4,6 +4,7 @@ use soroban_sdk::{ contract, contracterror, contractimpl, contracttype, symbol_short, token, Address, Env, Symbol, Vec, }; +use shared_utils::math::SafeMath; // ============================================================================ // Error Types @@ -446,9 +447,9 @@ impl CommitmentMarketplace { MarketplaceError::NotInitialized })?; - // Calculate fee and seller proceeds - let marketplace_fee = (listing.price * fee_basis_points as i128) / 10000; - let seller_proceeds = listing.price - marketplace_fee; + // Calculate fee and seller proceeds safely + let marketplace_fee = SafeMath::percent(listing.price, fee_basis_points); + let seller_proceeds = SafeMath::sub(listing.price, marketplace_fee); // EFFECTS // Remove listing first (prevent reentrancy) @@ -564,6 +565,22 @@ impl CommitmentMarketplace { return Err(MarketplaceError::InvalidOfferAmount); } + // Check if offerer is the seller of an active listing + if let Some(listing) = e.storage().persistent().get::<_, Listing>(&DataKey::Listing(token_id)) { + if listing.seller == offerer { + e.storage().instance().set(&DataKey::ReentrancyGuard, &false); + return Err(MarketplaceError::CannotBuyOwnListing); + } + } + + // Check if offerer is the seller of an active auction + if let Some(auction) = e.storage().persistent().get::<_, Auction>(&DataKey::Auction(token_id)) { + if auction.seller == offerer { + e.storage().instance().set(&DataKey::ReentrancyGuard, &false); + return Err(MarketplaceError::CannotBuyOwnListing); + } + } + // EFFECTS let offer = Offer { token_id, @@ -632,6 +649,13 @@ impl CommitmentMarketplace { // CHECKS seller.require_auth(); + if seller == offerer { + e.storage() + .instance() + .set(&DataKey::ReentrancyGuard, &false); + return Err(MarketplaceError::CannotBuyOwnListing); + } + let offers: Vec = e .storage() .persistent() @@ -673,9 +697,9 @@ impl CommitmentMarketplace { MarketplaceError::NotInitialized })?; - // Calculate fee and seller proceeds - let marketplace_fee = (offer.amount * fee_basis_points as i128) / 10000; - let seller_proceeds = offer.amount - marketplace_fee; + // Calculate fee and seller proceeds safely + let marketplace_fee = SafeMath::percent(offer.amount, fee_basis_points); + let seller_proceeds = SafeMath::sub(offer.amount, marketplace_fee); // EFFECTS // Remove all offers for this token @@ -816,7 +840,10 @@ impl CommitmentMarketplace { // EFFECTS let started_at = e.ledger().timestamp(); - let ends_at = started_at + duration_seconds; + let ends_at = started_at.checked_add(duration_seconds).ok_or_else(|| { + e.storage().instance().set(&DataKey::ReentrancyGuard, &false); + MarketplaceError::InvalidDuration + })?; let auction = Auction { token_id, @@ -1034,9 +1061,9 @@ impl CommitmentMarketplace { // INTERACTIONS if let Some(winner) = auction.highest_bidder { - // Calculate fees - let marketplace_fee = (auction.current_bid * fee_basis_points as i128) / 10000; - let seller_proceeds = auction.current_bid - marketplace_fee; + // Calculate fees safely + let marketplace_fee = SafeMath::percent(auction.current_bid, fee_basis_points); + let seller_proceeds = SafeMath::sub(auction.current_bid, marketplace_fee); let payment_token_client = token::Client::new(&e, &auction.payment_token); diff --git a/contracts/commitment_marketplace/src/tests.rs b/contracts/commitment_marketplace/src/tests.rs index 6127f87d..545e88c2 100644 --- a/contracts/commitment_marketplace/src/tests.rs +++ b/contracts/commitment_marketplace/src/tests.rs @@ -294,6 +294,53 @@ fn test_make_duplicate_offer_fails() { client.make_offer(&offerer, &1, &600, &payment_token); // Should fail } +#[test] +#[should_panic(expected = "Error(Contract, #8)")] // CannotBuyOwnListing +fn test_make_offer_own_listing_fails() { + let e = Env::default(); + e.mock_all_auths(); + + let (_, _, client) = setup_marketplace(&e); + + let seller = Address::generate(&e); + let payment_token = setup_test_token(&e); + + client.list_nft(&seller, &1, &1000, &payment_token); + client.make_offer(&seller, &1, &800, &payment_token); // Seller making offer on own listing +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] // CannotBuyOwnListing +fn test_make_offer_own_auction_fails() { + let e = Env::default(); + e.mock_all_auths(); + + let (_, _, client) = setup_marketplace(&e); + + let seller = Address::generate(&e); + let payment_token = setup_test_token(&e); + + client.start_auction(&seller, &1, &1000, &86400, &payment_token); + client.make_offer(&seller, &1, &1100, &payment_token); // Seller making offer on own auction +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] // CannotBuyOwnListing +fn test_accept_offer_own_listing_fails() { + let e = Env::default(); + e.mock_all_auths(); + + let (_, _, client) = setup_marketplace(&e); + + let seller = Address::generate(&e); + let payment_token = setup_test_token(&e); + + client.make_offer(&seller, &1, &1000, &payment_token); + client.accept_offer(&seller, &1, &seller); // Seller accepting own offer +} + + + #[test] fn test_multiple_offers_same_token() { let e = Env::default(); From f1f3f729d7293f441acd566904d953bc08938d5f Mon Sep 17 00:00:00 2001 From: Tijesunimi <110995878+Tijesunimi004@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:31:30 +0100 Subject: [PATCH 2/3] Update contracts/commitment_marketplace/src/lib.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- contracts/commitment_marketplace/src/lib.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/contracts/commitment_marketplace/src/lib.rs b/contracts/commitment_marketplace/src/lib.rs index d8caefc8..5c11e0dd 100644 --- a/contracts/commitment_marketplace/src/lib.rs +++ b/contracts/commitment_marketplace/src/lib.rs @@ -1061,8 +1061,15 @@ impl CommitmentMarketplace { // INTERACTIONS if let Some(winner) = auction.highest_bidder { - // Calculate fees safely - let marketplace_fee = SafeMath::percent(auction.current_bid, fee_basis_points); + // Calculate fees safely using basis points (bps, /10_000) + let fee_bps = if fee_basis_points > 10_000 { + 10_000 + } else { + fee_basis_points + }; + let fee_bps_i128 = fee_bps as i128; + let marketplace_fee = + SafeMath::div(SafeMath::mul(auction.current_bid, fee_bps_i128), 10_000_i128); let seller_proceeds = SafeMath::sub(auction.current_bid, marketplace_fee); let payment_token_client = token::Client::new(&e, &auction.payment_token); From 189131bd5a75615e11125d9d400298743aa7c7d7 Mon Sep 17 00:00:00 2001 From: Tijesunimi <110995878+Tijesunimi004@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:36:00 +0100 Subject: [PATCH 3/3] Update contracts/commitment_marketplace/src/lib.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- contracts/commitment_marketplace/src/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contracts/commitment_marketplace/src/lib.rs b/contracts/commitment_marketplace/src/lib.rs index 5c11e0dd..1eb7366f 100644 --- a/contracts/commitment_marketplace/src/lib.rs +++ b/contracts/commitment_marketplace/src/lib.rs @@ -447,8 +447,10 @@ impl CommitmentMarketplace { MarketplaceError::NotInitialized })?; - // Calculate fee and seller proceeds safely - let marketplace_fee = SafeMath::percent(listing.price, fee_basis_points); + // Calculate fee and seller proceeds safely using basis points (bps) + let fee_basis_points_i128: i128 = fee_basis_points as i128; + let marketplace_fee = + SafeMath::div(SafeMath::mul(listing.price, fee_basis_points_i128), 10_000_i128); let seller_proceeds = SafeMath::sub(listing.price, marketplace_fee); // EFFECTS