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 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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

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 removed this marketplace fee from the asset

});
}

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

.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

Peartes and others added 8 commits October 24, 2025 15:51
- 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
* chore: add in base spec msgs

* chore: asset method trait

* chore: implement default plugins

* chore: listing an asset

* chore: more coverage on Listing

* chore: delist and buy WIP on timelocks

* chore: unit test on delist

* chore: reserve and reserve unit test

* chore: more generic contract

* feat: add in default plugins

* feat: add in test and asset-base contract

* chore: disable raw transfer if royalty is set

* feat: add in query messages

* fix: remove default features for asset-base

* feat: make sure deductions are made in sellable buy logic

* chore: add in query impl into asset-base contract

* format toml

* add marketplace to lockfile

* add cw-address-like

* add contract

* update marketplace

* add queries

* add tests

* move offers

* add item-sold event

* complete buy

* offers

* add more tests

* remove unused

* accept offer

* change to queue

* set fee recipient and update config by manager

* chore: remove unwrap()

* fix: proper seller is owner

* fix linting

* check listing is tied to seller

* add justfile

* fix clippy issues

* add royalty test

* Merge pull request #86 from burnt-labs/feature/marketplace-approval

add approve/reject

* update cargo file, finalize for and split execute

* account for marketplace fees

---------

Signed-off-by: Kehinde Faleye <[email protected]>
Co-authored-by: peartes <[email protected]>
* handle asset price

* split tests

* fix tests

* fix lint

* format code
@Peartes Peartes requested a review from ash-burnt October 29, 2025 16:16
Peartes and others added 3 commits October 30, 2025 16:21
* fix fee on approval

* apply fee on accept offer

* format

* add tests

* update test and approval

---------

Co-authored-by: Kehinde Faleye <[email protected]>
* fmt code

* handle linter fixes for account, user map and treasury contracts

* handle asset lint issues

* format code
@justinbarry justinbarry changed the title chore: add in xion asset base spec msgs Asset + Marketplace Contract Nov 10, 2025
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.

4 participants