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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions