Skip to content

feat(token): implement two-step ownership transfer pattern#38

Merged
p3ris0n merged 3 commits into
BCPathway:mainfrom
ACodehunter:feature/two-step-ownership-issue-14
May 8, 2026
Merged

feat(token): implement two-step ownership transfer pattern#38
p3ris0n merged 3 commits into
BCPathway:mainfrom
ACodehunter:feature/two-step-ownership-issue-14

Conversation

@ACodehunter
Copy link
Copy Markdown
Contributor

Summary

Implements a secure two-step ownership transfer pattern for the token contract as specified in Issue #14. This prevents permanent loss of admin access due to typos or incorrect addresses.

Problem

The current transfer_ownership() function immediately transfers admin rights in a single step. If the new address is incorrect (typo, wrong key), the admin role is irrecoverably lost.

Solution

Implemented a two-step ownership transfer pattern:

  1. propose_owner(new_admin) - Current admin proposes a new admin
  2. accept_ownership() - Pending admin accepts the transfer
  3. cancel_transfer() - Current admin can cancel a pending transfer
  4. pending_owner() - Read-only function to check pending transfers

Changes

Contract Updates (lib.rs)

  • New Storage Key: DataKey::PendingAdmin
  • New Functions:
    • propose_owner(): Propose new admin (admin-only)
    • accept_ownership(): Accept pending transfer (pending admin only)
    • cancel_transfer(): Cancel pending transfer (admin-only)
    • pending_owner(): Query pending admin address
  • Deprecated: transfer_ownership() marked with deprecation notice in docs

Events (events.rs)

  • emit_ownership_proposed(): Emitted when admin is proposed
  • emit_ownership_accepted(): Emitted when transfer is accepted
  • emit_ownership_cancelled(): Emitted when transfer is cancelled

Tests (test.rs)

Added 5 comprehensive tests:

  1. Happy path: propose → accept → new admin can mint
  2. Accept without proposal fails: Panics with no pending transfer
  3. Cancel transfer: Clears pending admin
  4. Cancel without proposal fails: Panics with no pending transfer
  5. Double propose: Updates pending admin (second proposal overrides first)

Acceptance Criteria

  • ✅ New DataKey::PendingAdmin storage key
  • propose_owner, accept_ownership, cancel_transfer, pending_owner functions
  • ✅ Only the pending admin can accept
  • ✅ Only the current admin can propose or cancel
  • ✅ Events emitted for propose, accept, and cancel
  • ✅ Minimum 5 tests covering happy path, unauthorized accept, cancel, double-propose
  • ✅ Backward compatibility: old transfer_ownership() still works (deprecated)

Security Benefits

  • Typo Protection: Admin can verify the correct address before transfer
  • Recovery: Mistakes can be cancelled before acceptance
  • Confirmation: New admin must actively accept, confirming they have the correct keys
  • Transparency: Pending transfers are publicly queryable

Migration Path

Existing code using transfer_ownership() will continue to work. New code should use:

// Instead of:
contract.transfer_ownership(&new_admin);

// Use:
contract.propose_owner(&new_admin);
// Then new_admin calls:
contract.accept_ownership();

Closes #14

- Add DataKey::PendingAdmin for storing pending admin address
- Add propose_owner() for admin to propose new admin
- Add accept_ownership() for pending admin to accept transfer
- Add cancel_transfer() for admin to cancel pending transfer
- Add pending_owner() read-only function to check pending transfers
- Mark old transfer_ownership() as deprecated in docs
- Add events: emit_ownership_proposed, emit_ownership_accepted, emit_ownership_cancelled
- Add 5 comprehensive tests:
  * Happy path: propose -> accept -> new admin can mint
  * Accept without proposal fails
  * Cancel transfer clears pending admin
  * Cancel without proposal fails
  * Double propose updates pending admin
- Improves security: prevents permanent loss of admin access due to typos

Closes BCPathway#14
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented Apr 24, 2026

@ACodehunter 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

@p3ris0n
Copy link
Copy Markdown
Contributor

p3ris0n commented Apr 27, 2026

@ACodehunter please fix issues

@p3ris0n p3ris0n merged commit e7f4f3d into BCPathway:main May 8, 2026
0 of 2 checks passed
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.

[Contract]: Implement two-step ownership transfer pattern

2 participants