Skip to content

feat(soroban): implement NFT metadata update authorization check in Liquid Staking contract - #1058

Closed
0xDeon wants to merge 1 commit into
ceejaylaboratory:mainfrom
0xDeon:feat/issue-987-soroban-nft-metadata-auth
Closed

0xDeon wants to merge 1 commit into
ceejaylaboratory:mainfrom
0xDeon:feat/issue-987-soroban-nft-metadata-auth

Conversation

@0xDeon

@0xDeon 0xDeon commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Closes #987

The authorization check already exists

update_contract_meta already required admin authorization on main: it calls require_auth() on the caller and compares against the stored admin, panicking with OnlyAdmin otherwise. test_update_contract_meta_non_admin already covered it.

The issue's premise that any caller can rewrite staking position metadata does not hold against the current code, so the authorization check is left as-is and covered by additional tests rather than reimplemented. Flagging this explicitly in case the issue was written against an older revision.

What was genuinely missing

  • No length bound. description, icon_url, and website were written to instance storage at whatever length was supplied, so a single update could commit the contract to unbounded storage rental. Any field longer than MAX_METADATA_LEN (256 bytes) is now rejected with a new MetadataUriTooLong error. The bound is inclusive, so exactly 256 bytes is accepted.
  • Event shape. The event carried only the ContractMetadata struct, so a subscriber wanting the new URI had to destructure it. The data now leads with icon_url, keeping the full struct behind it so existing consumers continue to work.
  • Tests did not compile. Added the missing Events import to the test module, without which the crate's test target failed to build.

Test evidence

cargo test -p liquid_staking
test result: ok. 25 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

25 tests pass (17 pre-existing, 8 new), covering a non-admin update being rejected and leaving prior metadata intact, a URI at exactly the limit, each field rejected one byte over, an oversized update leaving state untouched, and the event being emitted.

Note on the contracts/ workspace

This workspace has a pre-existing, unrelated dependency break: soroban-env-host 22.1.3 fails to compile against ed25519-dalek 3.0.0 (an unpinned transitive bump), which blocks all test builds there. I pinned dalek to 2.2.0 locally to run the tests but deliberately did not commit that lockfile change, since it is a separate concern from this issue. Worth its own PR.

The issue body says Closes #83, but this repo's issue is #987; the template number appears stale.

update_contract_meta already required admin authorization: it calls
require_auth() on the caller and compares it against the stored admin,
panicking with OnlyAdmin otherwise, and test_update_contract_meta_non_admin
covered that. The issue's premise that any caller can rewrite the staking
position metadata does not hold against the current code, so the
authorization check is left as it is and covered by additional tests rather
than reimplemented.

What was genuinely missing is any bound on what the admin can store. The
description, icon_url, and website strings were written to instance storage
at whatever length was supplied, so a single update could commit the
contract to unbounded storage rental. Reject any field longer than
MAX_METADATA_LEN (256 bytes) with a new MetadataUriTooLong error. The bound
is inclusive, so a URI of exactly 256 bytes is accepted.

The emitted event carried only the ContractMetadata struct, so a subscriber
wanting the new URI had to destructure it. Lead the event data with
icon_url, keeping the full struct behind it so existing consumers continue
to work.

Also add the missing `Events` import to the test module, without which the
crate's tests did not compile at all.

Tests cover a non-admin update being rejected and leaving prior metadata
intact, a URI at exactly the limit being accepted, each of the three fields
being rejected one byte over, an oversized update leaving state untouched,
and the update emitting an event.

25 tests pass (17 pre-existing, 8 new).
@drips-wave

drips-wave Bot commented Aug 26, 2026

Copy link
Copy Markdown

@0xDeon 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! 🚀

Learn more about application limits

@0xDeon

0xDeon commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #1068, which combines this with the other three Soroban contract PRs into a single branch. Commit and tests carried over unchanged.

@0xDeon 0xDeon closed this Aug 27, 2026
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.

[Soroban] Implement NFT metadata update authorization check in Liquid Staking contract

1 participant