From 26d0ca070747cb766afbcc69b2f2d66f01d32018 Mon Sep 17 00:00:00 2001 From: Rob Konsdorf Date: Tue, 18 Aug 2026 16:20:56 -0400 Subject: [PATCH] docs: state that no per-listing guard caps the execution-time collection fee The execution-time fee section warned that an author's fee change hits every open listing, but not that a seller has no counter to it: assertsale takes no fee parameter, so nothing can pin a maximum fee into a settlement transaction. The advisory previously lived only on a wiki page that was retired. --- reference/atomicmarket/fees-and-royalties.md | 4 +++- validation-log.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/reference/atomicmarket/fees-and-royalties.md b/reference/atomicmarket/fees-and-royalties.md index 906c513..0c7b74a 100644 --- a/reference/atomicmarket/fees-and-royalties.md +++ b/reference/atomicmarket/fees-and-royalties.md @@ -35,7 +35,9 @@ Source: `src/atomicmarket.cpp:174-248` (`setmarketfee`, `addbonusfee`), `src/ato `announcesale`, `announceauct`, and `createbuyo` all read the collection's fee once at creation and store it on the row (`collection_fee`), but that stored value is written only for indexing: the `lognew*` actions emit it so indexers can display a listing's fee without a second lookup. At settlement, `internal_payout_sale` calls `partial_read_collection` again and uses whatever the collection's fee is at that moment, completely ignoring the value stored on the row. A collection author can raise or lower the fee at any time and the new rate applies immediately to every already-open listing; the buyer still pays the listed price, so only the seller/collection split moves. The live value is re-asserted to `0 <= fee <= 0.15` before use, because a fee outside that range (including a negative value, which is undefined behavior once cast to an unsigned integer) must not reach the payout math. -Source: `src/atomicmarket.cpp:2593-2609` (live collection fee read and range check), `src/atomicmarket.cpp:744-809` (`announcesale` storing the listing-time fee for logging only) +Nothing lets a seller cap this exposure per listing: `assertsale` asserts the asset ids, the listing price, and the settlement symbol, and takes no fee parameter, so no guard action can pin a maximum collection fee for a settlement. A front end that shows a seller the expected payout reads the live collection fee at the moment of sale rather than the `collection_fee` stored on the row. + +Source: `src/atomicmarket.cpp:2593-2609` (live collection fee read and range check), `src/atomicmarket.cpp:744-809` (`announcesale` storing the listing-time fee for logging only), `src/atomicmarket.cpp:993-1015` and `include/atomicmarket.hpp:206` (`assertsale` parameter list, with no fee field) ## The royalty split engine divides the collection fee among founders, templates, and attributes diff --git a/validation-log.md b/validation-log.md index 2bec346..c192b46 100644 --- a/validation-log.md +++ b/validation-log.md @@ -48,7 +48,7 @@ WAX mainnet still runs the V1 `atomicassets` and `atomicmarket` contracts (confi | `reference/atomicassets/tables.md` | `atomicassets-contract` (v2.0.0-rc4): `src/atomicassets.cpp`, `include/atomicassets.hpp` | source-read | One table per section, each with its own `Source:` line. | | `reference/atomicassets/v2-upgrade.md` | `atomicassets-contract` (v2.0.0-rc4) source; live `get_abi`/`get_table_rows` reads against WAX mainnet, jungle4, and wax-testnet | both | The additive-upgrade mechanics are source-read; the deployment-status section is live-chain, cross-checked across all three chains (mainnet V1, jungle4 and wax-testnet V2). Records that `config.version` reads `1.3.3` even on the V2 deployments, so table presence, not the version string, is the authoritative V2 check. | | `reference/atomicmarket/actions.md` | `atomicmarket-contract` (v2.0.0-rc2): `src/atomicmarket.cpp`, `include/atomicmarket.hpp` | source-read | Every action cites header and implementation line ranges. | -| `reference/atomicmarket/fees-and-royalties.md` | `atomicmarket-contract` (v2.0.0-rc2): `src/atomicmarket.cpp`, `include/atomicmarket.hpp`; live wax-testnet sale settlement | both | Cites `internal_payout_sale`, fee-bound actions, and the royalty split/log actions by line range. The four-layer fee stack, the founders/template/attribute split summing exactly to the collection fee, the standing 2% WAX bonus fee, and the `/sales/{id}/logs` payout read are live-chain-confirmed by a cold-validation trade run on wax-testnet. | +| `reference/atomicmarket/fees-and-royalties.md` | `atomicmarket-contract` (v2.0.0-rc2): `src/atomicmarket.cpp`, `include/atomicmarket.hpp`; live wax-testnet sale settlement | both | Cites `internal_payout_sale`, fee-bound actions, and the royalty split/log actions by line range. The four-layer fee stack, the founders/template/attribute split summing exactly to the collection fee, the standing 2% WAX bonus fee, and the `/sales/{id}/logs` payout read are live-chain-confirmed by a cold-validation trade run on wax-testnet. The no-fee-parameter `assertsale` note (no per-listing seller cap on the execution-time fee) is source-read. | | `reference/atomicmarket/marketplaces.md` | `atomicmarket-contract` (v2.0.0-rc2): `src/atomicmarket.cpp`, `include/atomicmarket.hpp` | source-read | Cites `regmarket`, `is_valid_marketplace`, and the maker/taker crediting logic inside `internal_payout_sale`. | | `reference/atomicmarket/ram.md` | `atomicmarket-contract` (v2.0.0-rc2): `src/atomicmarket.cpp`, `include/atomicmarket.hpp` | source-read | Cites the internal balance helpers and each `pay*ram` action by line range. | | `reference/atomicmarket/tables.md` | `atomicmarket-contract` (v2.0.0-rc2): `include/atomicmarket.hpp` | source-read | One table per section, each with its own header line-range citation. |