Skip to content

Commit

Permalink
Merge pull request from GHSA-vhw8-fgf8-2xcm
Browse files Browse the repository at this point in the history
add amount to accept offer
  • Loading branch information
jhernandezb committed Jun 3, 2024
2 parents 3969890 + 05b6971 commit b9780c3
Show file tree
Hide file tree
Showing 14 changed files with 931 additions and 627 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contracts/marketplace/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sg-marketplace"
version = "1.7.0"
version = "1.8.0"
authors = [
"Shane Vitarana <[email protected]>",
"Jake Hartnell <[email protected]>",
Expand Down
10 changes: 9 additions & 1 deletion contracts/marketplace/schema/sg-marketplace.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"contract_name": "sg-marketplace",
"contract_version": "1.5.0",
"contract_version": "1.8.0",
"idl_version": "1.0.0",
"instantiate": {
"$schema": "http://json-schema.org/draft-07/schema#",
Expand Down Expand Up @@ -459,11 +459,15 @@
"accept_bid": {
"type": "object",
"required": [
"amount",
"bidder",
"collection",
"token_id"
],
"properties": {
"amount": {
"$ref": "#/definitions/Uint128"
},
"bidder": {
"type": "string"
},
Expand Down Expand Up @@ -585,11 +589,15 @@
"accept_collection_bid": {
"type": "object",
"required": [
"amount",
"bidder",
"collection",
"token_id"
],
"properties": {
"amount": {
"$ref": "#/definitions/Uint128"
},
"bidder": {
"type": "string"
},
Expand Down
3 changes: 3 additions & 0 deletions contracts/marketplace/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ pub enum ContractError {
#[error("BidExpired")]
BidExpired {},

#[error("InvalidBidAmount: Expected {0} Found: {1}")]
InvalidBidAmount(Uint128, Uint128),

#[error("BidNotStale")]
BidNotStale {},

Expand Down
15 changes: 15 additions & 0 deletions contracts/marketplace/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ pub fn execute(
collection,
token_id,
bidder,
amount,
finder,
} => execute_accept_bid(
deps,
Expand All @@ -222,6 +223,7 @@ pub fn execute(
api.addr_validate(&collection)?,
token_id,
api.addr_validate(&bidder)?,
amount,
maybe_addr(api, finder)?,
),
ExecuteMsg::RejectBid {
Expand Down Expand Up @@ -267,6 +269,7 @@ pub fn execute(
collection,
token_id,
bidder,
amount,
finder,
} => execute_accept_collection_bid(
deps,
Expand All @@ -275,6 +278,7 @@ pub fn execute(
api.addr_validate(&collection)?,
token_id,
api.addr_validate(&bidder)?,
amount,
maybe_addr(api, finder)?,
),
ExecuteMsg::SyncAsk {
Expand Down Expand Up @@ -672,13 +676,15 @@ pub fn execute_remove_bid(
}

/// Seller can accept a bid which transfers funds as well as the token. The bid may or may not be associated with an ask.
#[allow(clippy::too_many_arguments)]
pub fn execute_accept_bid(
deps: DepsMut,
env: Env,
info: MessageInfo,
collection: Addr,
token_id: TokenId,
bidder: Addr,
amount: Uint128,
finder: Option<Addr>,
) -> Result<Response, ContractError> {
nonpayable(&info)?;
Expand All @@ -691,6 +697,9 @@ pub fn execute_accept_bid(
if bid.is_expired(&env.block) {
return Err(ContractError::BidExpired {});
}
if bid.price != amount {
return Err(ContractError::InvalidBidAmount(amount, bid.price));
}

if asks().may_load(deps.storage, ask_key.clone())?.is_some() {
asks().remove(deps.storage, ask_key)?;
Expand Down Expand Up @@ -864,13 +873,15 @@ pub fn execute_remove_collection_bid(
}

/// Owner/seller of an item in a collection can accept a collection bid which transfers funds as well as a token
#[allow(clippy::too_many_arguments)]
pub fn execute_accept_collection_bid(
deps: DepsMut,
env: Env,
info: MessageInfo,
collection: Addr,
token_id: TokenId,
bidder: Addr,
amount: Uint128,
finder: Option<Addr>,
) -> Result<Response, ContractError> {
nonpayable(&info)?;
Expand All @@ -883,6 +894,10 @@ pub fn execute_accept_collection_bid(
if bid.is_expired(&env.block) {
return Err(ContractError::BidExpired {});
}
if bid.price != amount {
return Err(ContractError::InvalidBidAmount(amount, bid.price));
}

collection_bids().remove(deps.storage, bid_key)?;

if asks().may_load(deps.storage, ask_key.clone())?.is_some() {
Expand Down
2 changes: 2 additions & 0 deletions contracts/marketplace/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ pub enum ExecuteMsg {
collection: String,
token_id: TokenId,
bidder: String,
amount: Uint128,
finder: Option<String>,
},
/// Reject a bid on an existing ask
Expand All @@ -114,6 +115,7 @@ pub enum ExecuteMsg {
collection: String,
token_id: TokenId,
bidder: String,
amount: Uint128,
finder: Option<String>,
},
/// Privileged operation to change the active state of an ask when an NFT is transferred
Expand Down
5 changes: 5 additions & 0 deletions contracts/marketplace/src/testing/tests/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ fn try_start_trading_time() {
collection: collection.to_string(),
token_id: minter_1_token_id_0,
bidder: bidder.to_string(),
amount: Uint128::from(100u128),
finder: None,
};
let res = router.execute_contract(creator.clone(), marketplace.clone(), &accept_bid_msg, &[]);
Expand Down Expand Up @@ -308,6 +309,7 @@ fn try_start_trading_time() {
collection: collection_2.to_string(),
token_id: minter_2_token_id_0,
bidder: bidder2.to_string(),
amount: Uint128::from(150u128),
finder: None,
};
let res = router.execute_contract(creator.clone(), marketplace.clone(), &accept_bid_msg, &[]);
Expand All @@ -322,6 +324,7 @@ fn try_start_trading_time() {
collection: collection_2.to_string(),
token_id: minter_2_token_id_0,
bidder: bidder2.to_string(),
amount: Uint128::from(150u128),
finder: None,
};

Expand All @@ -345,6 +348,7 @@ fn try_start_trading_time() {
collection: collection_2.to_string(),
token_id: minter_2_token_id_0,
bidder: bidder.to_string(),
amount: Uint128::from(100u128),
finder: None,
};
let res = router.execute_contract(creator.clone(), marketplace.clone(), &accept_bid_msg, &[]);
Expand Down Expand Up @@ -394,6 +398,7 @@ fn try_start_trading_time() {
collection: collection_2.to_string(),
token_id: minter_2_token_id_0,
bidder: bidder2.to_string(),
amount: Uint128::from(100u128),
finder: None,
};

Expand Down
3 changes: 3 additions & 0 deletions contracts/marketplace/src/testing/tests/auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,11 @@ fn set_auction_bids() {
collection: collection.to_string(),
token_id,
bidder: bidder.to_string(),
amount: Uint128::from(200u128),
finder: None,
};
let res = router.execute_contract(creator.clone(), marketplace.clone(), &accept_bid_msg, &[]);

assert!(res.is_ok());
// ask should have been removed
let res: AskResponse = router
Expand Down Expand Up @@ -234,6 +236,7 @@ fn transfer_accept_bid() {
collection: collection.to_string(),
token_id,
bidder: bidder.to_string(),
amount: Uint128::from(200u128),
finder: None,
};
let res = router.execute_contract(owner.clone(), marketplace.clone(), &accept_bid_msg, &[]);
Expand Down
123 changes: 123 additions & 0 deletions contracts/marketplace/src/testing/tests/bids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,7 @@ fn try_collection_bids() {
collection: collection.to_string(),
token_id,
bidder: bidder.to_string(),
amount: Uint128::from(150u128),
finder: None,
};

Expand Down Expand Up @@ -926,6 +927,7 @@ fn try_set_accept_bid_high_fees() {
collection: collection.to_string(),
token_id,
bidder: bidder.to_string(),
amount: Uint128::from(10000u128),
finder: Some(owner.to_string()),
};
let res = router.execute_contract(creator.clone(), marketplace.clone(), &accept_bid_msg, &[]);
Expand Down Expand Up @@ -1231,6 +1233,7 @@ fn try_set_accept_bid_no_ask() {
collection: collection.to_string(),
token_id,
bidder: bidder.to_string(),
amount: Uint128::from(100u128),
finder: None,
};
let res = router.execute_contract(creator.clone(), marketplace.clone(), &accept_bid_msg, &[]);
Expand Down Expand Up @@ -1422,6 +1425,7 @@ fn try_set_accept_fixed_price_bid() {
collection: collection.to_string(),
token_id,
bidder: bidder.to_string(),
amount: Uint128::from(100u128),
finder: None,
};
let res = router.execute_contract(creator.clone(), marketplace.clone(), &accept_bid_msg, &[]);
Expand Down Expand Up @@ -1575,3 +1579,122 @@ fn try_bid_sale_type() {
assert_eq!(res.bids.len(), 1);
assert_eq!(res.bids[0].price.u128(), 100u128);
}

#[test]
fn try_accept_bid_amount() {
let vt = standard_minter_template(1);
let (mut router, creator, bidder) = (vt.router, vt.accts.creator, vt.accts.bidder);
let marketplace = setup_marketplace(&mut router, creator.clone()).unwrap();
let minter_addr = vt.collection_response_vec[0].minter.clone().unwrap();
let collection = vt.collection_response_vec[0].collection.clone().unwrap();
let token_id = 1;
let start_time = Timestamp::from_nanos(GENESIS_MINT_START_TIME);
setup_block_time(&mut router, GENESIS_MINT_START_TIME, None);
// Mint NFT for creator
mint(&mut router, &creator, &minter_addr);
approve(&mut router, &creator, &collection, &marketplace, token_id);

// Bidder makes bid
let set_bid_msg = ExecuteMsg::SetBid {
sale_type: SaleType::Auction,
collection: collection.to_string(),
token_id,
finders_fee_bps: None,
expires: start_time.plus_seconds(MIN_EXPIRY + 1),
finder: None,
};
let res = router.execute_contract(
bidder.clone(),
marketplace.clone(),
&set_bid_msg,
&coins(100, NATIVE_DENOM),
);
assert!(res.is_ok());

// Creator accepts bid
let accept_bid_msg = ExecuteMsg::AcceptBid {
collection: collection.to_string(),
token_id,
bidder: bidder.to_string(),
amount: Uint128::from(200u128),
finder: None,
};
// fails because is not expected price
let res = router.execute_contract(creator.clone(), marketplace.clone(), &accept_bid_msg, &[]);
assert!(res.is_err());
// Creator accepts bid
let accept_bid_msg = ExecuteMsg::AcceptBid {
collection: collection.to_string(),
token_id,
bidder: bidder.to_string(),
amount: Uint128::from(100u128),
finder: None,
};
let res = router.execute_contract(creator.clone(), marketplace.clone(), &accept_bid_msg, &[]);
assert!(res.is_ok());
}

#[test]
fn try_collection_bid_amount() {
let vt = minter_two_collections(1);
let (mut router, owner, bidder, creator) =
(vt.router, vt.accts.owner, vt.accts.bidder, vt.accts.creator);
let marketplace = setup_marketplace(&mut router, owner).unwrap();
let minter_addr = vt.collection_response_vec[0].minter.clone().unwrap();
let collection = vt.collection_response_vec[0].collection.clone().unwrap();
let start_time = Timestamp::from_nanos(GENESIS_MINT_START_TIME);
setup_block_time(&mut router, GENESIS_MINT_START_TIME, None);

add_funds_for_incremental_fee(&mut router, &creator, INITIAL_BALANCE, 1u128).unwrap();

let token_id = 1;

setup_block_time(&mut router, start_time.nanos(), None);
// Mint NFT for creator
mint(&mut router, &creator, &minter_addr);
approve(&mut router, &creator, &collection, &marketplace, token_id);

// A collection bid is made by the bidder
let set_collection_bid = ExecuteMsg::SetCollectionBid {
collection: collection.to_string(),
finders_fee_bps: None,
expires: start_time.plus_seconds(MIN_EXPIRY + 10),
};
let res = router.execute_contract(
bidder.clone(),
marketplace.clone(),
&set_collection_bid,
&coins(150, NATIVE_DENOM),
);
assert!(res.is_ok());

// A collection bid is accepted but should fail
let accept_collection_bid = ExecuteMsg::AcceptCollectionBid {
collection: collection.to_string(),
token_id,
bidder: bidder.to_string(),
amount: Uint128::from(200u128),
finder: None,
};

// fails because does not match expected price
let res = router.execute_contract(
creator.clone(),
marketplace.clone(),
&accept_collection_bid,
&[],
);
assert!(res.is_err());

// A collection bid is accepted
let accept_collection_bid = ExecuteMsg::AcceptCollectionBid {
collection: collection.to_string(),
token_id,
bidder: bidder.to_string(),
amount: Uint128::from(150u128),
finder: None,
};

let res = router.execute_contract(creator.clone(), marketplace, &accept_collection_bid, &[]);
assert!(res.is_ok());
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::testing::helpers::funds::{
use crate::testing::helpers::nft_functions::{approve, mint};
use crate::testing::setup::setup_accounts::INITIAL_BALANCE;
use crate::testing::setup::setup_marketplace::{setup_marketplace, LISTING_FEE, MIN_EXPIRY};
use cosmwasm_std::{Addr, Timestamp};
use cosmwasm_std::{Addr, Timestamp, Uint128};
use cw721::{Cw721QueryMsg, OwnerOfResponse};
use cw_multi_test::Executor;
use sg_std::GENESIS_MINT_START_TIME;
Expand Down Expand Up @@ -120,6 +120,7 @@ fn try_bid_finders_fee() {
collection: collection.to_string(),
token_id,
bidder: bidder.to_string(),
amount: Uint128::from(100u128),
finder: Some(finder.to_string()),
};
let res = router.execute_contract(creator.clone(), marketplace.clone(), &accept_bid_msg, &[]);
Expand Down
Loading

0 comments on commit b9780c3

Please sign in to comment.