Repository navigation
feat(registry): upgradeable admin with two-step ownership handoverΒ #8
Copy link
Copy link
Open
Labels
complexity: mediumStandard features or involved bug fixes (150 pts)Standard features or involved bug fixes (150 pts)enhancementNew feature or requestNew feature or requestexternal-contributorsSuitable for contributors outside the maintainer teamSuitable for contributors outside the maintainer team
Description
π Sidera β Stellar Name Service. Contribute via Drips Wave / GrantFox. Comment with your approach and wait for assignment before starting.
Description
The pricing tranche introduces an admin (fee config authority), and the protocol will need more admin-gated knobs over time. But admin-style authorities that can be set by a single call are the classic rug handle for a name service. The house pattern for this ecosystem is a two-step handover: the current admin proposes a new admin, the proposed admin accepts.
Desired outcome: an Admin record with propose_admin(new) / accept_admin() two-step transfer, used by all admin-gated functionality going forward.
Scope
- Crate/module:
crates/registry,src/lib.rs - API:
propose_admin(env, new_admin),accept_admin(env), read-onlyadmin()andpending_admin() - Storage:
DataKey::Admin+DataKey::PendingAdmin(instance storage β small hot config) - Tests: first-initialization behavior; propose requires current admin; accept requires the proposed address; pending cleared after accept; re-propose flow;
acceptwith no pending β error - Docs: admin section in
docs/+ README note
Non-goals
- Multisig admin (a future integration β the admin CAN be a multisig contract address)
- Upgradeability of the contract WASM itself (out of scope; immutability is a feature)
- Time-locked admin actions
- Migration tooling
What "done" looks like
-
propose_adminrequires current-admin auth; stores pending -
accept_adminrequires the PROPOSED address's auth; promotes and clears pending -
admin()before any proposal β NotFound or an explicit uninitialized variant (pick, document, test) - Re-propose while a pending exists overwrites the pending (documented)
- Old admin retains no power after acceptance (proven by a test that their next admin call fails)
- All gates pass
Implementation guidelines
- If the pricing tranche (separate issue) has already introduced an admin, REFACTOR it onto this two-step module rather than duplicating authority logic β note the dependency in your PR
- Initialization decision to document: lazy init on first
propose_adminwhen unset (the first proposer becomes admin) vs an explicitinitializeβ lazy init is simpler; either is acceptable if tested - Error discipline: reuse
Unauthorized; addNoPendingAdminat the next free code if needed - Instance storage for both keys; TTL extension follows the house pattern
Verification
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test -p sidera-registry --all-targets --locked
PR guidelines
- Get assigned before starting; do not start work on a reserved issue.
- Work in a fork; branch off
upstream/main; open the PR againstSidera-Protocol/sidera-contracts:main. - PR description must include
Closes #8. - All CI checks must pass; human maintainer review required.
Metadata
- Affected crates/files:
contracts/registry/src/lib.rs,docs/ - Complexity label:
complexity: medium(150 base points) - Type labels:
enhancement
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
complexity: mediumStandard features or involved bug fixes (150 pts)Standard features or involved bug fixes (150 pts)enhancementNew feature or requestNew feature or requestexternal-contributorsSuitable for contributors outside the maintainer teamSuitable for contributors outside the maintainer team
Activity
Rodrigoue9 commentedon Oct 7, 2026
Hi @maintainer! I would like to implement the two-step admin ownership handover.
Architectural Plan:
DataKey::AdminandDataKey::PendingAdminin instance storage with appropriate TTL extension matching existing house patterns.contracts/registry/src/lib.rs:propose_admin(env, new_admin: Address): Enforcescurrent_admin.require_auth(), storesDataKey::PendingAdmin. Re-proposing overwrites pending.accept_admin(env): Enforcespending_admin.require_auth(), promotes toDataKey::Admin, and purgesDataKey::PendingAdmin. Returns error if no pending admin exists.admin(env) -> Option<Address>andpending_admin(env) -> Option<Address>.accept_admin.-D warnings), formatting, and test coverage across all handover paths.Track Record
Please assign this issue to me to begin implementation!