Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions contracts/asset/src/execute/sale.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ where
.ok_or_else(|| ContractError::NoPayment {})?
.clone();

// check for underpayment but overpayment are absorbed if an exact price
// plugin is not set on the asset
// check for underpayment
if payment.amount.lt(&price.amount) || payment.denom != price.denom {
return Err(ContractError::InvalidPayment {
price: payment.amount.u128(),
Expand All @@ -58,6 +57,23 @@ where

let mut response = Response::<TCustomResponseMsg>::default();

// defense-in-depth: cap payment to listing price and refund any excess
// to the buyer. The ExactPrice plugin rejects overpayment outright when
// configured; this ensures the seller never silently receives more than
// the listing price even when the plugin is absent.
if payment.amount.gt(&price.amount) {
let refund_amount = payment.amount.checked_sub(price.amount)
.map_err(|_| ContractError::InsufficientFunds {})?;
response = response.add_message(BankMsg::Send {
to_address: info.sender.to_string(),
amount: vec![Coin {
denom: payment.denom.clone(),
amount: refund_amount,
}],
});
payment.amount = price.amount;
}

// remove all other deductions e.g. royalties from payment
for (_, amount, _) in deductions {
payment.amount = payment
Expand Down
10 changes: 10 additions & 0 deletions contracts/asset/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,13 @@ where
) -> StdResult<bool> {
// for buys we run the exact price, then allowed marketplaces and royalty plugins if set
let config = AssetConfig::<TNftExtension>::default();
let exact_price_plugin = config.collection_plugins.may_load(
ctx.deps.storage,
Plugin::ExactPrice {
amount: cosmwasm_std::coin(0, ""),
}
.get_plugin_name(),
)?;
let allowed_marketplaces_plugin = config.collection_plugins.may_load(
ctx.deps.storage,
Plugin::AllowedMarketplaces {
Expand All @@ -405,6 +412,9 @@ where
id: token_id.to_string(),
})?;
ctx.data.ask_price = Some(listing.price.clone());
if let Some(plugin) = exact_price_plugin {
plugin.run_asset_plugin(ctx)?;
}
if let Some(plugin) = allowed_currencies_plugin {
plugin.run_asset_plugin(ctx)?;
}
Expand Down
Loading