AtomicMarket v2.0.0-rc2
Pre-releaseThe AtomicMarket v2 contract, release candidate 2. Built from master (integration branch v2/integration-rc1) with CDT 4.1.1. This describes the whole v2 change and supersedes rc1.
AtomicMarket v2 is a breaking upgrade, unlike the non-breaking AtomicAssets v2. Every listing now holds exactly one asset, legacy multi-asset bundles auto-cancel when touched, and the collection fee is charged at execution time. The v2 dependency on AtomicAssets is now limited to reading templates2 mutable template data for royalty attribute matching. Upgrading is a setcode plus setabi. Existing single-asset sales, auctions and buyoffers keep working and on-chain state is preserved; legacy bundle rows are cancelled when touched rather than migrated, as described under Breaking changes.
Changes since rc1: custodial rentals descoped
Custodial rentals have been removed from the v2 release train so the rest of v2 can ship without them (#13). The implementation is preserved on the archive/v2-custodial-rentals branch; whether and how rentals return has not been decided. The removal takes out:
- Actions:
announcerent,cancelrent,rentasset,endrent,payrentram - Log actions:
lognewrent,logrentstart,logrental - Table:
rentals - The
rentalbranch of the transfer memo handling, the rental ricardian contracts, and the rentals wiki and API documentation
The ABI diff against rc1 is exactly this surface. With rentals gone, v2 no longer uses the AtomicAssets v2 holders table or move action (which the paired AtomicAssets v2.0.0-rc4 also removed).
This candidate also completes the test migration off Hydra (#10): the remaining v1 suite gaps were ported to VeRT as new admin, auctions, buyoffers, deposit-withdraw and sales suites, taking the suite from 47 to 220 tests. Test-only, no contract changes.
What v2 adds
Royalty splits. By default the collection fee goes to the collection author. An author can instead split it across weighted categories: a global founders list, per-template recipient lists, and attribute rules that match a (field, value) on the asset, such as rarity = legendary. Configuration lives in the new royaltyconf, royaltytemp and royaltyattr tables. Settlement emits logroy* actions whose amounts sum exactly to the collection fee, so an indexer can record the final per-recipient amounts without reimplementing the split. Payouts accrue to balances and are claimed with withdraw; nothing is transferred inline, so a recipient contract cannot block a collection's settlements.
Single-asset listings (breaking). announcesale, announceauct and createbuyo reject more than one asset. This keeps per-asset attribution of the collection fee and royalties exact. Listing or buying several assets in one transaction covers what bundles were previously used for.
Execution-time collection fee (breaking). Settlement reads the collection's market_fee live from AtomicAssets at execution time, not the fee stored when the listing was created. A fee change by the author, whether a discount or an increase, applies immediately to every existing listing. The listing row's collection_fee is informational only.
Default-marketplace admin (XPR portability). setdefmktcr redirects the empty-name default marketplace's fee recipient at runtime, and migratebal merges accumulated balances. Together they let one binary run on chains where the seeded fees.atomic account does not exist.
CPU optimizations. Tables are constructed lazily per action, the config singleton is deserialized at most once per action, the AtomicAssets collections row is read through a size-capped partial read that takes only the author and market fee rather than the full row, and notification handlers bind with [[eosio::on_notify]].
New actions
Royalty config: setroyalconf, delroyalconf, settemplroy, deltemplroy, setattrroy, delattrroy. Royalty logs: logroyfound, logroytempl, logroyattr, logroydust. Default-marketplace admin: setdefmktcr, migratebal. The existing sale, auction, buyoffer and tbuyoffer actions keep their signatures; their behavior changes are noted above. The final surface is 51 actions and 12 tables.
New tables
royaltyconf, royaltytemp, royaltyattr. The existing tables (sales, auctions, buyoffers, tbuyoffers, config, balances, marketplaces, bonusfees, counters) keep their layout.
Breaking changes and migration
- Single-asset only. A new sale, auction or buyoffer must reference exactly one asset.
- Legacy bundles are cancelled, not migrated. A pre-v2 row with more than one asset auto-cancels when touched.
purchasesalecancels the sale and charges the buyer nothing. A bid or claim on a bundle auction dissolves it, refunding the bid and returning the assets.acceptbuyoon a bundle refunds the buyer.cancelsaleandcancelaucton bundles may be called by anyone. A partially-claimed bundle auction is finished through the normal claim actions, with the collection fee paid to the author in full and no royalty logs emitted. Activating a bundle (offer memosaleor transfer memoauctionwith more than one asset) aborts. - Execution-time fee. Because the fee is read at settlement, an author can change it within the 15% cap after a listing is created. The buyer always pays the listed price; only the split between seller and collection moves. A front end should show the live fee at the point of sale.
Hardening carried from rc1
The base v2 contract (PRs #1 to #3, authored by t-break) went through three adversarial review passes that found no critical or high theft or fund-loss. Six follow-up PRs merged into rc1:
- #4 fee-ceiling bound.
setmarketfeeandaddbonusfeereject a configuration whose fees plus the maximum collection fee exceed the price, andinternal_payout_saleasserts a positive seller payout as the runtime backstop. - #5 is_permutation size guards.
assertsale,assertauctandacceptbuyouse the four-iterator overload, which compares lengths and avoids the out-of-bounds read the v2 rewrite had introduced. - #6 low-level hardening. Re-assert that the execution-time fee is between 0 and 15% (a negative double cast to
uint64_tis undefined behavior), and guard the empty AtomicAssets offers table before--end()inacceptbuyoandfulfilltbuyo. - #7 default-marketplace admin. Adds
setdefmktcrandmigratebal, with acheck(from != to)guard that prevents a balance-doubling fund loss. - #8 ABI verification in CI.
patch-abi.pynow self-asserts idempotency and gains a--verify-againstmode that proves only the two sanctioned spelling changes were applied; CI also parses the patched ABI with@wharfkit/antelope. - #9 documentation. Documents the seller-facing tradeoff of the execution-time fee.
To review the full v2 change, diff the tags: git diff v1.3.3 v2.0.0-rc2. v1.3.3 is the pre-v2 baseline and the version currently deployed on WAX mainnet. For the delta from the previous candidate alone, git diff v2.0.0-rc1 v2.0.0-rc2.
Build and verification
Built with cdt-cpp 4.1.1. The published ABI is the legacy-compat patched build produced by make release: vector<uint8_t> fields render as uint8[] and pair fields keep their first and second key/value spellings, so integrations that read the ABI keep working. The VeRT suite passes (6 suites, 220 tests) and the release ABI round-trips the CI --verify-against check.
rc2 is deployed and verified on both FACINGS testnets: the on-chain code hash on the WAX testnet and jungle4 equals the atomicmarket.wasm sha256 below, and get_abi on both chains shows the full royalty and admin surface with no rental actions. This is the first AtomicMarket v2 deployment on any chain.
Artifacts
| asset | sha256 |
|---|---|
atomicmarket.wasm |
5016d9560574cce18f511de41d4ba1e81c4d30526c4452f0f70c3e59d64e7ed3 |
atomicmarket.abi |
e1b480faeb6f59f8f474af28677907a25d0d58e455d5a951f2315a87012177a9 |
Verify against the attached SHA256SUMS.
Deploying
The artifacts are pinned by sha256 in the FACINGS monorepo chain-config (the testnet atomicmarket entries) and deployed via the contracts-deploy workflow using the atomicmarket@deploy permission, which is linked to eosio::setcode and eosio::setabi. Mainnet and XPR keep compiling the vendored v1.3.3 source until the v2 production cutover. Pre-release, for testnet.
Credits
AtomicMarket is part of the AtomicAssets NFT ecosystem created by Pink Network, with stewardship passing from Pink Network to Spielworks and then to FACINGS. The v1 contract was written by Jona Wilmsmann (Pink Network). Most of the v2 contract was written by t-break (@on-a-t-break). The v2 review, the hardening PRs, the XPR port, the VeRT test migration and this release were done by the FACINGS team.