Architecture Overview
Tech Stack
| Layer | Technology | Version |
|---|---|---|
| Language | Solidity | ^0.8.34 |
| Framework | Foundry (forge) | v10.x |
| Math | PRB Math | v4.1.2 |
| Contracts | OpenZeppelin | v5.6.1 |
| Token Standards | ERC20, ERC1155, ERC2981, ERC165 | — |
| Transient Storage | EIP-1153 (ReentrancyGuardTransient) | — |
| License | GPL-3.0 | — |
Optimizer is enabled by default for builds (foundry.toml profile). Tests run with optimizer disabled via FOUNDRY_OPTIMIZER=false. Compiler warnings 2394, 3860, 5574, 4591, and 6335 are suppressed.
Version & Networks
- Protocol Version:
0x10c1(10.2.0), stored asConstant.VERSIONatsource/contracts/libs/Constant.sol:44 - Network Mainnet: Avalanche C-Chain (chain ID
43114) - Network Testnet: Avalanche Fuji (chain ID
43113)
All contracts expose uint256 public constant VERSION = Constant.VERSION (via Supervised or NftTreasury).
Source Layout
source/
├── contracts/
│ ├── XPower.sol # core: PoW ERC20 token (alias: moe)
│ ├── XPowerNft.sol # core: deposit receipt ERC1155 (alias: nft)
│ ├── APowerNft.sol # core: staking receipt ERC1155 (alias: ppt)
│ ├── APower.sol # core: store-of-value ERC20 (alias: sov)
│ ├── MoeTreasury.sol # core: reward distributor (alias: mty)
│ ├── NftTreasury.sol # core: staking manager (alias: nty)
│ ├── base/
│ │ ├── NftBase.sol # ERC1155 base: NFT ID math, supply tracking
│ │ ├── NftMigratable.sol # ERC1155 migration: old→new NFT bridging
│ │ ├── NftRoyalty.sol # EIP-2981: 0.5% royalty with configurable beneficiary
│ │ ├── URIMalleable.sol # Per-year mutable metadata URIs (permanent after decade)
│ │ ├── Supervised.sol # Role-based access control hierarchy
│ │ └── Migratable.sol # ERC20 migration: MoeMigratable + SovMigratable
│ └── libs/
│ ├── Constant.sol # Time constants, decimals, protocol version
│ ├── Nft.sol # NFT ID composition: idBy(year, level), yearOf, levelOf, denominationOf
│ ├── Power.sol # Fractional exponentiation via PRB Math pow()
│ ├── Polynomials.sol # eval3/eval4/eval5/eval6: linear+power evaluation
│ ├── Integrator.sol # Δ-stamp weighted arithmetic mean over (stamp, value) items
│ ├── Banq.sol # Auto-supply to lending pool with excess-burning safety
│ ├── Rpp.sol # Rug-pull protection: parameter change guardrails
│ └── Array.sol # sorted() and unique() array validatorsInheritance Tree
XPower (moe)
ERC20 → ERC20Permit, ERC20Burnable → Migratable → MoeMigratableSupervised → Supervised → AccessControl
↘︎
Ownable
↗︎
XPower ──→ ERC20Permit, ERC20Burnable, MoeMigratable, OwnableKey parent: ERC20Permit for gasless approvals, ERC20Burnable for burn, Ownable for mint authorization, MoeMigratable for migration from legacy v9.x contracts.
XPowerNft (nft)
ERC1155 → ERC1155Supply, ERC1155Burnable → URIMalleable → URIMalleableSupervised
→ NftRoyalty → NftRoyaltySupervised
→ NftMigratable → NftMigratableSupervised
→ Ownable
NftBase ──→ ERC1155, ERC1155Supply, ERC1155Burnable, URIMalleable, NftRoyalty, NftMigratable, Ownable
↗︎
XPowerNft ──→ NftBaseAPowerNft (ppt)
NftBase (same chain as XPowerNft)
APowerNft ──→ NftBase, ReentrancyGuardTransientAdds ReentrancyGuardTransient (EIP-1153) for safe transfer reentrancy protection. onlyOwner restricts mint/burn to NftTreasury.
APower (sov)
ERC20 → ERC20Permit, ERC20Burnable → Migratable → SovMigratable (Migratable + Banq + ReentrancyGuardTransient)
↘︎
Ownable
↗︎
APower ──→ ERC20Permit, ERC20Burnable, SovMigratable, OwnableDirectly references XPower for wrap/unwrap operations. onlyOwner restricts mint to MoeTreasury.
MoeTreasury (mty)
MoeTreasurySupervised → Supervised → AccessControl
Banq → Supervised → AccessControl
MoeTreasury ──→ ReentrancyGuardTransient, MoeTreasurySupervised, Ownable, BanqIntegrates 5 libraries: Polynomials, Integrator, Array, Power, Banq, Rpp. Constructor sets owner to NftTreasury address.
NftTreasury (nty)
ERC1155Holder
NftTreasury ──→ ERC1155HolderMinimal contract — holds staked XPowerNft tokens, interacts bidirectionally with APowerNft and MoeTreasury.
Contract Relationship Diagram
┌──────────────┐
│ XPower │ (moe) ERC20 PoW token
│ mint() │
└──────┬───────┘
│ deposit XPOW
▼
┌──────────────────────────────┐
│ XPowerNft │ (nft) ERC1155 deposit receipt
│ mint(account, level, amount)│
│ burn(account, id, amount) │
│ upgrade(account, anno, ...) │
└──────────────┬───────────────┘
│ safeTransferFrom → nty
▼
┌─────────────────────────────────────────────────────┐
│ NftTreasury (nty) ERC1155Holder │
│ stake(account, nftId, amount) │
│ unstake(account, nftId, amount) │
└──────┬──────────────────────────────────┬───────────┘
│ ppt.mint / ppt.burn │ refreshRates()
▼ ▼
┌──────────────┐ ┌──────────────────────┐
│ APowerNft │ (ppt) │ MoeTreasury (mty) │
│ ageOf() │ │ claim(account, ...) │
│ shares() │ │ aprOf() / apbOf() │
└──────────────┘ │ rewardOf() │
│ setAPR() / setAPB() │
└──────────┬────────────┘
│ sov.mint(to, claim)
▼
┌──────────────────────┐
│ APower (sov) │
│ mint(to, claim) │
│ burn(amount) → unwrap│
│ metric() │
└──────────────────────┘Flow summary:
- Mining: User calls
XPower.init()to cache block hash, thenXPower.mint(to, blockHash, data)with a valid nonce. XPOW minted to both beneficiary and treasury owner (doubling supply). - Deposit: User calls
XPowerNft.mint(account, level, amount)— XPOW transferred to NFT contract, ERC1155 receipt minted. - Stake: User calls
NftTreasury.stake(account, nftId, amount)— XPowerNft locked in treasury, APowerNft minted as staking receipt. - Claim: User calls
MoeTreasury.claim(account, nftId, amount, nonce)— reward calculated from age × rate × denomination, APOW minted at rate-limited pace. - Unwrap: User calls
APower.burn(amount)— APOW burned, proportional XPOW returned from treasury.
Role System
All roles are defined in Supervised.sol via AccessControl:
| Role | Admin Role | Scope | Description |
|---|---|---|---|
DEFAULT_ADMIN_ROLE | — | Global | Grant/revoke all roles |
APR_ROLE | APR_ADMIN_ROLE | MoeTreasury | Set APR polynomial parameters |
APB_ROLE | APB_ADMIN_ROLE | MoeTreasury | Set APB polynomial parameters |
MOE_SEAL_ROLE | MOE_SEAL_ADMIN_ROLE | XPower | Seal MOE immigration |
SOV_SEAL_ROLE | SOV_SEAL_ADMIN_ROLE | APower | Seal SOV immigration |
NFT_SEAL_ROLE | NFT_SEAL_ADMIN_ROLE | NftMigratable | Seal NFT immigration |
NFT_OPEN_ROLE | NFT_OPEN_ADMIN_ROLE | NftMigratable | Open NFT emigration |
NFT_ROYAL_ROLE | NFT_ROYAL_ADMIN_ROLE | NftRoyalty | Set royalty beneficiary |
URI_DATA_ROLE | URI_DATA_ADMIN_ROLE | URIMalleable | Set metadata URIs |
Each role follows a two-tier pattern: the _ROLE grants action rights, the _ADMIN_ROLE manages granters.
Key Design Decisions
onlyOwneron mint/burn:APowerNft.mint()/burn()andAPower.mint()areonlyOwner— ownership is transferred toNftTreasuryandMoeTreasuryrespectively in their constructors.- Double mint:
XPower.mint()mints to bothto(beneficiary) andowner()(treasury), effectively doubling supply on each PoW discovery. - Block hash expiry:
XPower.mint()requires block hash cached within the current 1-hour interval (block.timestamp / 3600). - NFT levels divisible by 3: All NFT levels must be multiples of 3 (0, 3, 6, ..., 99). The
Nft.idBy()function enforces this withlevel % 3 == 0. - Redemption maturity:
XPowerNfttokens are redeemable (burnable for underlying XPOW) whenyearOf(id) + 2^(level/3) - 1 <= year(). - Rate limit:
APower.mint()targets ~1 APOW per minute long-term average using a square-root scaling of claims. - Banq auto-supply: The
banqmodifier inMoeTreasury.claim()auto-supplies freshly minted APOW to a lending pool, burning any excess above the claim amount.