fix: dispatch royalty_info existence check through ContractType - #846
Conversation
The NonFungibleRoyalties default body called Base::royalty_info directly, which establishes existence with Base::owner_of. Under Consecutive only the last token of a batch has a materialised Owner entry, so every other token was rejected with OpenZeppelin#200 NonExistentToken even though Consecutive::owner_of resolves it correctly. The check now goes through Self::ContractType::owner_of, matching how every other default body in this library dispatches. Base::royalty_info_unchecked carries the lookup so Base::royalty_info keeps its current behaviour. Note this adds public API to a published crate. The _unchecked suffix follows credit_identity_unchecked in rwa/compliance/modules/max_balance, and the new function carries a Security Warning section as that precedent does. Adds a regression test asserting all 10 tokens of a batch resolve both an owner and royalty information. With the source reverted to main and the test kept, it fails on token 0 with OpenZeppelin#200 while the other 9 royalty tests pass.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. WalkthroughThe royalties extension now validates token ownership through ChangesRoyalty dispatch correction
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The PR corrects royalty lookup dispatch for consecutive token ownership and adds focused regression coverage; no actionable merge-blocking risk remains after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant ContractCaller
participant NonFungibleRoyalties
participant ContractType
participant Base
ContractCaller->>NonFungibleRoyalties: royalty_info(token_id, sale_price)
NonFungibleRoyalties->>ContractType: owner_of(token_id)
ContractType-->>NonFungibleRoyalties: owner
NonFungibleRoyalties->>Base: royalty_info_unchecked(token_id, sale_price)
Base-->>ContractCaller: royalty recipient and amount
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Fixes #845
Problem
NonFungibleRoyalties::royalty_info's default body calledBase::royalty_info, which establishes existence withBase::owner_of. UnderContractType = Consecutiveownership is stored sparsely: only the last token of a batch has a materialisedOwnerentry, and the rest are resolved by walking back through the bucket. Every non-boundary token was therefore rejected with#200 NonExistentToken.The library documents the correct pattern in
non_fungible/overrides.rs, and every sibling default body follows it.royalty_infowas the exception, which looks like it was missed when the default bodies landed in #604.Change
The existence check now goes through
Self::ContractType::owner_of, matching how every other default body in this library dispatches.The lookup itself moves into
Base::royalty_info_unchecked, soBase::royalty_infokeeps its current behaviour exactly: it still callsBase::owner_ofand then the same lookup.This adds public API to a published crate, which is worth flagging up front. The
_uncheckedsuffix followscredit_identity_uncheckedinrwa/compliance/modules/max_balance/storage.rs, and the new function carries a# Security Warningsection as that precedent does. If you would rather not grow the surface, the alternative is to putroyalty_infoonContractOverrideswith theBasebehaviour as the default and override it inConsecutive. Say the word and I will redo it that way.Evidence
test_royalty_info_resolves_every_token_under_consecutivebatch-mints ten tokens and asserts that each one resolves both an owner and royalty information.Reverting only the two source hunks and keeping the test gives:
The test also asserts
owner_ofanswers for all ten. That is the control: the tokens demonstrably exist andConsecutiveresolves them, so the failure is in the dispatch rather than the token.Checks
cargo +nightly fmt --all -- --checkcleancargo +stable clippy --release --locked --all-targets -- -D warningsexit 0cargo test -p stellar-tokenspasses: 714 tests, 713 before plus this one.nft-royalties-examplepassesSummary by CodeRabbit
Bug Fixes
Tests