Skip to content

Conversation

@Peartes
Copy link
Contributor

@Peartes Peartes commented Sep 16, 2025

This is the Asset standard Contract. Details on the design is here

@Peartes Peartes self-assigned this Sep 16, 2025
@Peartes Peartes added the enhancement New feature or request label Sep 16, 2025
@Peartes Peartes marked this pull request as ready for review October 20, 2025 14:15
@Peartes Peartes changed the title chore: add in base spec msgs chore: add in xion asset base spec msgs Oct 20, 2025
}

listing.reserved = Some(Reserve {
reserver: reservation.reserver.clone(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an unsafe call. Addr types are not sanitized from msgs. Even though the type is set, the address might be invalid, and needs to be checked


#[cw_serde]
pub struct Reserve {
pub reserver: Addr,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addr types are good for state storage, but not good for msg types, because of their lack of sanitization. You probably can't reuse the state definition for the msg definition. Also, you likely want to make the reserver optional, and if unset, uses the msg sender

.iter()
.find(|coin| coin.denom == price.denom)
.ok_or_else(|| ContractError::NoPayment {})?
.clone();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if multiple coins are sent? Seems like everything other than the first match will be stuck in the contract. If only one token is expected, it should be enforced

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjusted to fail the tx if multiple coins are sent

.ok_or_else(|| ContractError::NoPayment {})?
.clone();

if payment.amount.lt(&price.amount) || payment.denom != price.denom {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This checks if you underpaid, which is good, but does not check if you overpaid. Do we intend to let people overpay? If so, that will need to be explicitly documented

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have an exact price plugin that can be set to enforce the exact price of an asset is sent. If this isn't set, only underpayments are considered. Should we fail on overpayments regardless ?

id: String,
price: Coin,
reservation: Option<Reserve>,
marketplace_fee_bps: Option<u16>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This initialism is never defined anywhere. I don't know what it means

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is sent in the listing msg and is the marketplace fee in basis point

});
}

let (validated_marketplace_fee_bps, validated_marketplace_fee_recipient) =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like these marketplace values can be set by the lister. How do they interact with the marketplace? Why would someone listing an asset set them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

an individual listing an item would not set this. This is strictly for scenarios where marketplaces are the ones listing and want to set a fee


listing.reserved = Some(Reserve {
reserver: reservation.reserver.clone(),
reserved_until: reservation.reserved_until,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any bound on this value? Or can I just reserve something for 10,000,000 years?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a time lock plugin that sets the maximum duration an asset can be reserved for and is enforced upon reservation but if the time lock plugin is not set, the asset can be reserved indefinitely until unreserved by the owner or approvals

.add_attribute("price", price.amount.to_string())
.add_attribute("denom", price.denom)
.add_attribute("seller", seller.to_string())
.add_attribute("buyer", buyer.to_string());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't include all of the data necessary for backing out the pricing. marketplace configuration args should be output here as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they are included early if the marketplace config was set or not at all

- fail tx when multiple coins are set to make sure coins aren't stuck in contract

- make sure Abstract types without sanitation enforced aren't used in msgs and then directly for logic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants