Skip to content

v2 · Integration — Features 1-8 + 300 (dev-production-3) - #9

Merged
robrigo merged 52 commits into
mainfrom
feat/v2-integration
Jul 16, 2026
Merged

v2 · Integration — Features 1-8 + 300 (dev-production-3)#9
robrigo merged 52 commits into
mainfrom
feat/v2-integration

Conversation

@robrigo

@robrigo robrigo commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Full integrated v2 surface — the reference branch for the complete contract.


Mirrored into the canonical atomicassets org for the AtomicAssets v2 release + audit.
Original: wax-office-of-inspector-general/atomicassets-contract#12

⚠️ Hold — do not merge to master yet. Kept on a feature branch to avoid prod integration risk; pending the comprehensive v2 audit.

@robrigo
robrigo marked this pull request as ready for review June 2, 2026 20:49
@robrigo
robrigo requested a review from Copilot June 2, 2026 20:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR is an integrated AtomicAssets v2 contract surface update, adding new authoring/templating capabilities and a “holdership” concept while refactoring table access and notifications/auth checks for performance.

Changes:

  • Added new on-chain features: asset holdership via move + holders table, author swap offers (createauswap/acceptauswap/rejectauswap), schema type metadata (setschematyp), and mutable template data support (createtempl2/settempldata/deltemplate/redtemplmax).
  • Deprecated native token backing paths (mintasset now rejects tokens_to_back; backasset hard-fails; removed internal_back_asset usage).
  • Refactored table access to use get_*() fetch helpers and introduced a low-level partial row read for collection auth/notify lookups.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/atomicassets.cpp Implements new v2 actions/features, deprecates backing, updates transfer logic for holdership, and adds low-level collection partial reads.
include/checkformat.hpp Adjusts format validation to pass by reference.
include/atomicdata.hpp Adds FORMAT_TYPE to support schema type metadata.
include/atomicassets.hpp Extends contract ABI (new actions/tables), adds table fetch helpers, and updates internal function signatures.
include/atomicassets-interface.hpp Updates the external interface header to mirror new v2 tables/types and helper accessors.
Comments suppressed due to low confidence (1)

src/atomicassets.cpp:247

  • createcol() doesn't enforce the 24-element caps for authorized_accounts/notify_accounts that later code (partial_read_collection) relies on. A collection created with >24 entries can make partial_read_collection read too few bytes and cause unpack failures when checking auth / sending notifications.
    auto config = get_config();
    config_s current_config = config.get();

    collections.emplace(author, [&](auto &_collection) {
        _collection.collection_name = collection_name;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/atomicassets.cpp
Comment thread src/atomicassets.cpp
Comment thread src/atomicassets.cpp
Comment thread include/atomicassets-interface.hpp Outdated
Comment thread src/atomicassets.cpp Outdated
aaroncox and others added 5 commits June 5, 2026 08:00
…nto integration

Consolidates the full AtomicAssets v2 test suite onto feat/v2-integration so the
integration line is self-testable (make build && npx jest). feat/v2-integration
is an ancestor of the test branch, so this only adds the 16 test commits + Makefile.
Excludes PR #13 gap-fill (its byte-math suite asserts the PR #12 fix, which is held).
…ild)

CDT 4.1 -abigen changed two wire-compatible but tool-visible ABI spellings vs the
CDT used to compile the deployed AtomicAssets contract:
  1. std::pair fields  first/second  (was key/value)
  2. std::vector<uint8_t>  bytes       (was uint8[])
Both break existing integrations (atomicassets-js, wallets, ECA indexer, cleos
JSON) that pack/unpack ATTRIBUTE_MAP and serialized_data by these names, though
the compiled wasm and binary wire format are identical.

scripts/patch-abi.py restores the deployed spellings. It is applied ONLY by the
new `make release` target (build + patch) for distribution / cleos set contract;
the VeRT suite is written against the raw CDT 4.1 abi and runs on `make build`,
so the patch is deliberately kept out of the test path. Verified: after patching,
the rc abi's shared surface is byte-for-byte equivalent to on-chain get_abi
(only additive v2 features differ); wasm sha256 unchanged.
The atomicassets-contract repo had no CI. This adds a GitHub Actions workflow
that installs the pinned CDT (4.1.1, public .deb), builds the contract
(make build), and runs the @vaulta/vert jest suite on pushes to the v2 lines +
master and on all PRs. Runs on ubuntu-latest (the FACINGS monorepo's self-hosted
+ private-GHCR CI is not reachable from this public org).

A harness guard skips cleanly on refs without the test harness (e.g. master
before v2 lands), so the same workflow can live on master to gate its PRs/pushes
without failing until the suite arrives. Actions are SHA-pinned.
@robrigo

robrigo commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Attribution note for merging v2 to master: t-break's authorship is already preserved on the per-feature branches (and dev-production-3), so a merge that keeps those commits carries it at the commit level. If this is squash-merged instead, please include these trailers in the squash message so GitHub still attributes the authors on master:

Co-authored-by: t break <93979504+on-a-t-break@users.noreply.github.com>
Co-authored-by: Aaron Cox <677686+aaroncox@users.noreply.github.com>

AUTHORS.md records the full provenance (t-break for the bulk of v2, @aaroncox for the self-service RAM utilities, pink.network for the base contract).

robrigo and others added 17 commits June 9, 2026 17:28
…> FACINGS); AtomicAssets is the open standard, AtomicHub the marketplace
The interface header is consumed by external contracts (atomicpacks,
atomictools, atomicbridge, ...), never by atomicassets itself, so the main
VeRT suite cannot catch regressions in it. The v2 get_self() anchoring bug
(fixed in #21) shipped exactly because nothing in CI ever compiled the header
from a consumer's context — get_self() is a member of eosio::contract, so the
v2 header did not even compile for consumers.

Add a minimal consumer fixture (tests/fixtures/interface-consumer) built by
`make build` and deployed at `ifaceconsumr` in a new VeRT suite:
- the compile alone catches the get_self() class of regression
- the runtime tests catch any compilable-but-wrong-anchor variant: reads of
  collections (contract scope), assets (per-owner scope), and templates
  (per-collection scope) through the header from a non-atomicassets account,
  plus a negative control proving the checks execute

Verified red/green: with the pre-#21 header restored, the consumer build fails;
with the fixed header, 4/4 tests pass.
test: compile + read atomicassets-interface.hpp from a consumer contract
addcolauth and addnotifyacc cap each vector at 24, but createcol wrote both
verbatim with no size check. That let a single createcol seed a collection past
the cap and overflow partial_read_collection's fixed read window (auth path once
authorized > ~39; notify path once authorized+notify > 63), bricking
check_has_collection_auth / notify_collection_accounts for that collection. This
is the residual gap noted in #12, which fixes the read side but cannot bound an
unbounded write.

Add the same <=24 checks createcol was missing (identical messages to
addcolauth/addnotifyacc) plus VeRT cases: createcol with 25 authorized or 25
notify throws, and the 24+24 boundary succeeds. Full suite green (cdt-cpp 4.1.1).

Note: does not retroactively touch existing >24 collections; WAX mainnet has 0
collections above 24 authorized (max 23) and 1 with >24 notify (31), all well
within the post-#12 read budgets.
…y_accounts

The authorized-accounts path (type=false, 330-byte db_get_i64 buffer) deserialized
notify_accounts unconditionally, reading past the truncated buffer once a collection's
authorized+notify accounts exceeded ~38 -> 'datastream attempted to read past the end',
bricking every check_has_collection_auth caller (createschema/createtempl/setschematyp/
extendschema/...). Root cause: the byte-math budget assumed a phantom +128 row/PK prefix
that db_get_i64 does not return (it returns payload only), and the auth path was sized to
end-of-authorized (210B) while the code read to end-of-notify (403B).

Fix: early-return after authorized_accounts on the auth path (<=210B, within 330); the
notify path still reads through notify_accounts (<=403B, within 523). Behavior-preserving
for all previously-succeeding inputs; only un-bricks the previously-throwing auth case.
Correct the misleading byte-math comments. Closes audit A-BYTEMATH (the A.7 'safe' verdict
was wrong: verified vs eosio.cdt 4.1.1, reproduces on mainnet).
… over-read

Adds tests/Collection Actions/partial-read-collection-bytemath.test.js covering
the auth path at 19+19, the former 20+20 overflow boundary, and the max 24+24
authorized+notify caps, plus a 24-account notify-path read past a large
serialized_data. All four pass on the fixed contract; the 20+20 and 24+24 cases
throw 'datastream attempted to read past the end' on an unfixed build, so the
file fails the suite without the fix (real regression guard).

Validated locally with cdt-cpp 4.1.1 (make build + npx jest).
…bytemath

fix(atomicassets): partial_read_collection auth path over-reads notify_accounts (pre-mainnet blocker)
fix(atomicassets): cap createcol authorized/notify accounts at 24 (follow-up to #12)
The VeRT test dirs used Title Case with spaces (tests/Collection Actions/, etc.),
which is shell-hostile (needs quoting everywhere) and non-idiomatic. Rename all
nine to kebab-case (tests/collection-actions/, ...). The jest glob is **/*.test.js
so this is a pure rename: no config change, full suite still green (42 suites).
Also updates the two stale path references in the Makefile and interface-consumer
fixture comments. fixtures/ kept as-is.
chore(tests): rename test directories to kebab-case
Replace em dashes with plain punctuation across the Makefile, patch-abi.py, and a
few test comments. No code or behavior change; the deployed source (src, include,
README) was already clean.
Custodial rentals are descoped from the V2 release so the rest of V2 can
ship without them. The dual-ownership mechanism is removed in full:

- move action and logmove notification
- holders table (+ holders_s struct, get_holders accessor) in both the
  contract header and the consumer-facing interface header
- holder-erase block in burnasset
- holder bookkeeping in internal_transfer

No other V2 feature reads holder state, so this is a pure excision.
ABI diff vs v2.0.0-rc3: exactly move, logmove, holders(_s) removed.

Rentals live on: the custodial implementation is preserved on
archive/v2-custodial-rentals (and the v2.0.0-rc1..rc3 tags); the
non-custodial rework continues on experiment/noncustodial-rentals (#26).

Tests: move.test.js (16) and renting-invariants.test.js (3) deleted;
holder-specific cases removed from transfer.test.js and burnasset.test.js.
Suite: 40 suites, 324 passing (1 pre-existing skip).
feat!: remove custodial rental primitives (move/logmove/holders) from V2
This branch and the default branch each added the workflow independently, so the differing branch filters collide as an add/add conflict on merge. Matching the default branch resolves it and keeps one copy of the file after the merge.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 55 out of 59 changed files in this pull request and generated 6 comments.

Comment thread include/checkformat.hpp Outdated
Comment thread package.json
Comment thread README.md Outdated
Comment thread CLAUDE.md Outdated
Comment thread tests/template-actions/settempldata.test.js Outdated
Comment thread tests/template-actions/settempldata.test.js Outdated
…ater

check() evaluates both arguments, so the remaining-seconds message was built on every successful accept, and acceptance_date - now underflowed as uint32 to produce a string that was then discarded: wasted CPU in a release whose point is CPU cost. The strict comparison also rejected the acceptance_date second itself, so a swap became acceptable a second after the date it advertises. Both now sit behind an explicit branch, and a regression test pins the boundary by failing against the previous logic.

check_format took a non-const reference while never writing through it, leaving callers unable to pass a const format and readers unsure whether it mutated. The docstring claimed three weeks of validity where the code allows two from creation under active permissions and one under owner. The test-directory listings named directories that no longer exist, and two suites located inline actions by their position in the trace list rather than by name, so unrelated changes to inline dispatch would fail them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants