Holder snapshots, key metadata, flash-loan guard, settable co-creator split - #794
Merged
Conversation
…reator split - accesslayerorg#778 take_snapshot(admin, creator, snapshot_id, holders): records each holder's balance at the current ledger into a snapshot map, plus metadata (snapshot_ledger, total_holders). Soroban storage can't be enumerated on-chain, so `holders` is a caller-supplied list (e.g. from an indexer) rather than an internal registry walk, capped at MAX_SNAPSHOT_HOLDERS (100) per call the same way airdrop_keys caps recipients. Rejects a duplicate snapshot_id with SnapshotAlreadyExists, a non-admin caller with Unauthorized, and emits snapshot_taken. - accesslayerorg#779 initialise_key(creator, name, bio, avatar_uri): one-time on-chain identity metadata for a registered creator, validated against 64/256-byte caps, TTL-bumped on write, rejecting a second call with KeyAlreadyInitialised. Emits key_initialised. - accesslayerorg#781 flash-loan guard: buy_key records last_buy_ledger per (creator, holder); sell_key now rejects with FlashLoanDetected (and emits flash_loan_blocked) when attempted in that same ledger. Stored as a separate persistent entry rather than folded into the balance entry as the issue suggested, to avoid touching every one of the balance field's many existing read/write call sites across this file. - accesslayerorg#782 set_co_creator(creator, co_creator, split_bps): the registration-time co_creator config was previously immutable; this adds a standalone entrypoint (1-9000 bps, SplitTooHigh otherwise) a creator can call anytime to set or change it. Writes the same CoCreatorConfig storage the existing buy/sell fee-crediting path already reads, so per-trade splitting and the co_creator_fee_earned event needed no new code — only the missing setter and a co_creator_set event were added. Added creator-keys/src/test_issues_778_779_781_782.rs covering all four. I could not run cargo test/check in this environment — the host-target build itself fails at the linker step (MSVC misconfiguration) even on an untouched main checkout, unrelated to this change. Please treat CI as the source of truth and flag anything it catches that manual review missed.
|
@Davidemulo Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
- ContractError enum: kept upstream's new GlobalTradingHalted = 51 and renumbered this branch's accesslayerorg#778/accesslayerorg#779/accesslayerorg#781/accesslayerorg#782 variants to 52-58 so no discriminant collides (both sides used name-based references only, no numeric literals elsewhere, so renumbering is safe). - DataKey enum: unioned both sides' new variants (snapshot/metadata/ flash-loan-guard from this branch, global-pause variants from upstream) — no naming or numeric overlap between them. - buy_key_with_referrer: kept both this branch's flash-loan-guard write (LastBuyLedger, issue accesslayerorg#781 same-ledger resell guard) and upstream's lockup-window write (LastBuyTimestamp) side by side, then adopted upstream's newer fee flow (collect_protocol_trade_fee -> net_amount feeding the creator/protocol fee split) instead of splitting the fee on the gross price, since that's a real improvement independent of the flash-loan guard. - Discovered upstream/main's own tip references constants::storage::last_buy_timestamp() and a timestamp-keyed storage slot for it, but never defines either — upstream/main does not compile as committed. Added the missing DataKey::LastBuyTimestamp(Address, Address) variant and its storage helper, mirroring the existing LastBuyLedger pattern, so the merged tree builds. No local rustc/link toolchain available in this environment to run `cargo build`/`cargo test` (link.exe fails on build-script compilation unrelated to this change), so this merge is verified by manual review and exhaustive grep-based cross-checks of every symbol touched by the conflict instead.
…shloan-guard-co-creator
5 tasks
Adejumo-2
pushed a commit
to Adejumo-2/accesslayer-contracts
that referenced
this pull request
Aug 31, 2026
New code from PR accesslayerorg#794 (co-creator snapshot metadata) was unformatted. Run cargo fmt --all to pass the CI format check.
Seunfunmi-319509
pushed a commit
to Seunfunmi-319509/accesslayer-contracts
that referenced
this pull request
Sep 1, 2026
…dentation The merge that brought in PR accesslayerorg#794 truncated the cancel_auction function body, removing its closing braces and logic. The circuit breaker block inside buy_key also had wrong indentation from the merge, leaving an unclosed else delimiter that broke cargo fmt. - Restore the full cancel_auction function body (auction config lookup, auction_sold guard, storage removal, and event emission) - Re-indent the circuit breaker block inside the else branch so the outer `let price = if ... else { ... };` expression is properly closed - Run cargo fmt across the workspace 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
take_snapshot: records each holder's balance at the current ledger into a snapshot map, plus metadata (snapshot_ledger,total_holders). Soroban contract storage cannot be enumerated on-chain (there's no "iterate all keys with this prefix"), soholdersis a caller-supplied list — sourced off-chain, e.g. from an indexer — rather than an internal registry walk, exactly like the existingairdrop_keysentrypoint takes a caller-supplied recipient list. Capped atMAX_SNAPSHOT_HOLDERS(100) per call for the same reasonairdrop_keyscaps atMAX_AIRDROP_RECIPIENTS. Rejects a duplicatesnapshot_idwithSnapshotAlreadyExists, a non-admin caller withUnauthorized, and emitssnapshot_taken.initialise_key: one-time on-chain identity metadata (name/bio/avatar URI) for a registered creator, validated against 64/256-byte caps, TTL-bumped on write, rejecting a second call withKeyAlreadyInitialised. Emitskey_initialised.buy_keynow recordslast_buy_ledgerper(creator, holder);sell_keyrejects withFlashLoanDetected(and emitsflash_loan_blocked) when attempted in that same ledger. Stored as a separate persistent entry rather than folded into the balance entry as the issue's scope suggested ("Store last_buy_ledger in the same persistent entry as the holder balance") — the balance field is a plainu32read/written at dozens of call sites across this 6000-line file (buy, sell, transfer, dividends, snapshots, batch ops), and changing its shape to a struct would have meant touching all of them for a one-extra-storage-read optimization. Happy to fold it in as a follow-up if that tradeoff is wanted.co_creatorconfig (register_creator's optionalCoCreatorConfigparam) was previously immutable. This adds a standaloneset_co_creator(creator, co_creator, split_bps)entrypoint (1–9000 bps,SplitTooHighotherwise, distinct from the registration path's ownInvalidCoCreatorShare/1–9999 bound since the issue specifies a 90% cap) a creator can call anytime. It writes the sameCoCreatorConfigstorage the existing buy/sell fee-crediting path (credit_creator_fee) already reads — so per-trade splitting on both buy and sell, and theco_creator_fee_earnedevent, needed no new code; only the missing setter and aco_creator_setevent were added.Tests
Added
creator-keys/src/test_issues_778_779_781_782.rs— 19 tests covering the happy path and each documented error condition for all four issues, following this repo's existingtest_new_features.rssetup pattern (setup_test()/register_creator()helpers).Verification
I could not run
cargo check/cargo testin this environment — even an untouchedmaincheckout fails at the host-target build-script link step here (MSVC linker misconfiguration, unrelated to this change). Instead I did an extensive manual review: traced every existing call site of the storage/helper functions I reused (extend_key_ttl_to_full_window,assert_is_admin,read_registered_creator_profile,validate_non_zero_address,credit_creator_fee) to confirm argument types and borrow vs. move usage match; confirmedVec<Address>::iter()yields owned values consistent with this file's existing loop patterns (e.g.get_creators_batch); and checked the newContractError/DataKeyvariants are strictly appended (per this file's own ABI-stability doc comment onContractError). Please treat the repo's CI as the source of truth and flag anything it catches that manual review missed.Closes #778
Closes #779
Closes #781
Closes #782