Skip to content

refactor: adopt trait-based architecture (FungibleToken, FungibleBurnable, Pausable) #4

@aguilar1x

Description

@aguilar1x

Context

Depends on #3 (import paths). OZ v0.6.0 introduces a trait-based contract architecture. The current contract calls Base::* functions directly inside a monolithic #[contractimpl] block and does not implement any of the standard traits. The new standard requires implementing FungibleToken, FungibleBurnable, and Pausable as separate #[contractimpl] blocks.

Current structure (v0.3.0)

#[contractimpl]
impl MyStablecoin {
    pub fn transfer(env: Env, from: Address, to: Address, amount: i128) { ... }
    pub fn burn(env: Env, from: Address, amount: i128) { ... }
    pub fn pause(env: Env, caller: Address) { ... }
    // ...all methods in one block
}

Target structure (v0.6.0)

#[contractimpl]
impl FungibleToken for MyStablecoin {
    type ContractType = Base;

    #[when_not_paused]
    fn transfer(e: &Env, from: Address, to: MuxedAddress, amount: i128) {
        Self::ContractType::transfer(e, &from, &to, amount);
    }
    // ...
}

#[contractimpl]
impl FungibleBurnable for MyStablecoin {
    #[when_not_paused]
    fn burn(e: &Env, from: Address, amount: i128) {
        Self::ContractType::burn(e, &from, amount);
    }
    // ...
}

#[contractimpl]
impl Pausable for MyStablecoin {
    fn paused(e: &Env) -> bool { pausable::paused(e) }
    fn pause(e: &Env, caller: Address) { /* auth check + pausable::pause(e) */ }
    fn unpause(e: &Env, caller: Address) { /* auth check + pausable::unpause(e) */ }
}

Changes required

  • Split the monolithic impl MyStablecoin into multiple impl <Trait> for MyStablecoin blocks
  • Implement FungibleToken with type ContractType = Base
  • Implement FungibleBurnable
  • Implement Pausable (replaces extensions/pausable.rs)
  • Remove extensions/burnable.rs, extensions/pausable.rs, extensions/upgradeable.rs — their logic is now covered by the traits
  • Keep custom methods (e.g., initialize, mint, batch_mint, get_admin) in a plain impl MyStablecoin block
  • Replace if pausable::paused(&env) { return Err(...) } guards with the #[when_not_paused] attribute macro

Reference

See examples/fungible-pausable/src/contract.rs in the OZ repo for the canonical pattern.

Acceptance criteria

  • Contract implements FungibleToken, FungibleBurnable, Pausable traits
  • extensions/ directory only contains logic not covered by OZ traits
  • No manual if pausable::paused checks — use #[when_not_paused] instead
  • All existing tests pass

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions