Contract Reference
Core Contracts
XPower (moe) — Proof-of-Work Token
Source: source/contracts/XPower.sol:19Inheritance: ERC20Permit, ERC20Burnable, MoeMigratable, OwnableStandards: ERC20, EIP-2612 (permit), ERC165
Key Functions
function init() external;Caches the most recent block hash (blockhash(block.number - 1)) and its timestamp into a 1-hour interval slot. Must be called before mint() for each interval. Emits Init(bytes32 blockHash, uint256 timestamp).
function mint(address to, bytes32 blockHash, bytes calldata data) external;Verifies a proof-of-work nonce and mints tokens. data contains the nonce. Requirements:
blockHashmust be recent (within current 1-hour interval)- The
(nonceHash, blockHash)pair must be unique (duplicate prevention) - The nonce hash must have at least 1 leading zero nibble
- Mints
(2^zeros - 1) * 10^18XPOW to bothtoandowner()
function blockHashOf(uint256 interval) external view returns (bytes32);
function currentInterval() public view returns (uint256);
function decimals() public view virtual override returns (uint8);Events
| Event | Parameters |
|---|---|
Init | bytes32 indexed blockHash, uint256 timestamp |
Custom Errors
| Error | Trigger |
|---|---|
DuplicatePairIndex(bytes32 pair_index) | Nonce+block pair already used |
ExpiredBlockHash(bytes32 block_hash) | Block hash outside current hour |
EmptyNonceHash(bytes32 nonce_hash) | Nonce produced zero leading zeros |
Internal Logic
_hashOf(address to, bytes32 blockHash, bytes data)— computeskeccak256(address(this) ^ to, blockHash, data)→ returns(nonceHash, nonceHash ^ blockHash)for pair-index uniqueness_zerosOf(bytes32 nonceHash)— counts leading zero hex nibbles via63 - (log2(nonceHash) >> 2)_amountOf(uint256 level)— reward formula:(2^level - 1) * 10^decimals
XPowerNft (nft) — Deposit Receipt NFT
Source: source/contracts/XPowerNft.sol:11Inheritance: NftBase → ERC1155, ERC1155Supply, ERC1155Burnable, URIMalleable, NftRoyalty, NftMigratable, OwnableStandards: ERC1155, EIP-2981 (royalty), ERC165
Key Functions
function mint(address account, uint256 level, uint256 amount) external;Mints amount of NFTs at level for account. Transfers amount * denominationOf(level) XPOW from account to the contract as deposit. NFT ID = 100 * year() + level.
function mintBatch(address account, uint256[] memory levels, uint256[] memory amounts) external;Batch mints across multiple levels. Sums total XPOW deposit and transfers in single transferFrom.
function burn(address account, uint256 id, uint256 amount) public override;Burns amount of id NFTs from account. Returns the underlying XPOW deposit back to account. Only succeeds if the NFT is redeemable: yearOf(id) + 2^(levelOf(id)/3) - 1 <= year() or emigration is open.
function burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) public override;Batch burn with pre-check that all IDs are redeemable.
function upgrade(address account, uint256 anno, uint256 level, uint256 amount) external;Upgrades amount * 1000 NFTs at level - 3 to amount NFTs at level. Requires level > 2. Example: 1000× level-3 → 1× level-6, 1000× level-6 → 1× level-9.
function upgradeBatch(address account, uint256[] memory annos, uint256[][] memory levels, uint256[][] memory amounts) external;Batch upgrade across multiple years and levels.
function approveMint(address operator, bool approved) external;
function approveUpgrade(address operator, bool approved) external;Delegation: allows operator to mint or upgrade on behalf of caller.
function approvedMint(address account, address operator) public view returns (bool);
function approvedUpgrade(address account, address operator) public view returns (bool);
function idBy(uint256 anno, uint256 level) public pure returns (uint256);
function idsBy(uint256 anno, uint256[] memory levels) public pure returns (uint256[] memory);
function denominationOf(uint256 level) public pure returns (uint256);
function levelOf(uint256 nftId) public pure returns (uint256);
function yearOf(uint256 nftId) public pure returns (uint256);
function year() public view returns (uint256);Events
| Event | Parameters |
|---|---|
ApproveMinting | address indexed account, address indexed operator, bool approved |
ApproveUpgrading | address indexed account, address indexed operator, bool approved |
Inherited from NftBase/parents: TransferSingle, TransferBatch, ApprovalForAll, URI.
Custom Errors
| Error | Trigger |
|---|---|
IrredeemableIssue(uint256 nft_id) | Burn attempted before maturity |
NonTernaryLevel(uint256 level) | Level not divisible by 3 |
APowerNft (ppt) — Staking Receipt NFT
Source: source/contracts/APowerNft.sol:14Inheritance: NftBase, ReentrancyGuardTransientAccess Control: onlyOwner on mint(), burn(), mintBatch(), burnBatch() — owner is NftTreasury
Key Functions
function init(address mty) external;One-time post-constructor init. Sets the MoeTreasury reference. Emits Init(mty).
function mint(address account, uint256 nftId, uint256 amount) external onlyOwner;
function burn(address account, uint256 nftId, uint256 amount) public override onlyOwner;Mints/burns staked NFT receipts. onlyOwner restricts to NftTreasury. Updates age accumulators and share accumulators.
function ageOf(address account, uint256 nftId) external view returns (uint256);Returns age in seconds: balance * block.timestamp - _age[account][nftId]. Used by MoeTreasury.rewardOf() for reward calculation.
function shares() external view returns (int256[34] memory);Returns 34-element array of share accumulators per level tier (level / 3). Each entry accumulates amount * 10^level for mint and subtracts on burn. Used by MoeTreasury.refreshRates().
function safeTransferFrom(address account, address to, uint256 nftId, uint256 amount, bytes memory data) public override nonReentrant;
function safeBatchTransferFrom(address account, address to, uint256[] memory nftIds, uint256[] memory amounts, bytes memory data) public override nonReentrant;Overrides ERC1155 transfers to reset age tracking on transfer and refresh claimed amounts via MoeTreasury.refreshClaimed().
Events
| Event | Parameters |
|---|---|
Init | address mty |
Custom Errors
| Error | Trigger |
|---|---|
AlreadyInitialized(MoeTreasury moe_treasury) | init() called twice |
InsufficientBalance(uint256 balance) | Burn exceeds balance |
InvalidAmount(uint256 amount) | Zero amount |
EmptyAmounts() | Empty amounts array |
EmptyIds() | Empty IDs array |
LengthMismatch(uint256[] nft_ids, uint256[] amounts) | Array length mismatch |
APower (sov) — Store-of-Value Token
Source: source/contracts/APower.sol:18Inheritance: ERC20Permit, ERC20Burnable, SovMigratable, OwnableStandards: ERC20, EIP-2612 (permit)
Key Functions
function mint(address to, uint256 claim) external onlyOwner returns (uint256);Mints APOW at a rate-limited pace. Wraps wrappable(claim) XPOW from treasury, then computes mintable APOW via exponential moving average of claims. Returns the minted amount. onlyOwner restricts to MoeTreasury.
function wrappable(uint256 claim) public view returns (uint256);Returns min(claim, _moe.balanceOf(owner())) — the amount of XPOW available to wrap from the treasury balance.
function mintable(uint256 claim) external view returns (uint256);
function mintableBatch(uint256[] memory claims) external view returns (uint256[] memory);Preview the APOW amount that would be minted for a given claim without executing. Uses the long-term mean of claims: mean = (mean * time + sqrt(claim)) / t.
function burn(uint256 amount) public override;
function burnFrom(address account, uint256 amount) public override;Burns APOW and returns proportional XPOW from the contract's balance: unwrappable(amount) = balance * amount / (amount + totalSupply()).
function unwrappable(uint256 amount) public view returns (uint256);
function metric() external view returns (uint256);metric() returns APOW-to-XPOW backing ratio scaled to 1e18: 1e18 * balance / totalSupply().
Events
Inherited ERC20 events: Transfer, Approval.
MoeTreasury (mty) — Reward Distributor
Source: source/contracts/MoeTreasury.sol:25Inheritance: ReentrancyGuardTransient, MoeTreasurySupervised, Ownable, Banq
Key Functions
function claim(address account, uint256 nftId, uint256 amount, uint256 nonce) external nonReentrant banq(account, amount, nonce);Claims accumulated APOW rewards for a single staked NFT. Computes claimable(account, nftId), updates _claimed tracker, calls _sov.mint(), then the banq modifier auto-supplies to lending pool. Emits Claim.
function claimBatch(address account, uint256[] memory nftIds, uint256 amount, uint256 nonce) external nonReentrant banq(account, amount, nonce);Batch claim across multiple staked NFTs. Requires nftIds to be unique and sorted. Emits ClaimBatch.
function claimable(address account, uint256 nftId) public view returns (uint256);
function claimableBatch(address account, uint256[] memory nftIds) public view returns (uint256[] memory);Returns pending (unclaimed) XPOW reward: rewardOf(account, nftId) - claimed(account, nftId).
function rewardOf(address account, uint256 nftId) public view returns (uint256);Calculates reward: (aprOf(nftId) + apbOf(nftId)) * ageOf(account, nftId) * 10^18 * denominationOf(levelOf(nftId)) / (1e6 * CENTURY).
function mintable(address account, uint256 nftId) external view returns (uint256);
function mintableBatch(address account, uint256[] memory nftIds) external view returns (uint256[] memory);Preview APOW that would be minted for pending rewards via _sov.mintable(claimable(...)).
function aprOf(uint256 nftId) public view returns (uint256);
function aprTargetOf(uint256 nftId) public view returns (uint256);
function getAPR(uint256 nftId) public view returns (uint256[] memory);
function setAPR(uint256 nftId, uint256[] memory array) public onlyRole(APR_ROLE);
function setAPRBatch(uint256[] memory nftIds, uint256[] memory array) external onlyRole(APR_ROLE);APR (Annual Percentage Rate): level-based reward rate defined by a 4-coefficient polynomial [add, div, mul, exp]. Evaluated as: pow(mul * level / div + add, exp / 256). Protected by Rpp.checkValue (rate change ≤ 2×) and Rpp.checkStamp (≥ 1 month between changes).
function apbOf(uint256 nftId) public view returns (uint256);
function apbTargetOf(uint256 nftId) public view returns (uint256);
function getAPB(uint256 nftId) public view returns (uint256[] memory);
function setAPB(uint256 nftId, uint256[] memory array) public onlyRole(APB_ROLE);
function setAPBBatch(uint256[] memory nftIds, uint256[] memory array) external onlyRole(APB_ROLE);APB (Annual Percentage Bonus): vintage-based bonus for long-term stakers, depends on year() - yearOf(nftId).
function refreshRates(bool allLevels) external;Recalculates APR scalar for each level based on share distribution. Called by NftTreasury after every stake/unstake. Share-weighted scalar redistributes rewards toward under-staked levels.
function refreshClaimed(address account, uint256 nftId, uint256 balanceOld, uint256 balanceNew) external onlyOwner;Rescales _claimed when partial unstake occurs: claimed = claimed * balanceNew / balanceOld.
function claimed(address account, uint256 nftId) public view returns (uint256);
function minted(address account, uint256 nftId) public view returns (uint256);Trackers for claimed XPOW rewards and minted APOW totals per (account, nftId).
Events
| Event | Parameters |
|---|---|
Claim | address account, uint256 nftId, uint256 amount |
ClaimBatch | address account, uint256[] nftIds, uint256[] amounts |
SetAPR | uint256 nftId, uint256[] array |
SetAPB | uint256 nftId, uint256[] array |
RefreshRates | bool allLevels |
Custom Errors
| Error | Trigger |
|---|---|
NonUnique(uint256[] nft_ids) | Duplicate or unsorted IDs in batch claim |
InvalidClaim(uint256 nft_id) | Claim resulted in zero APOW |
NftTreasury (nty) — Staking Manager
Source: source/contracts/NftTreasury.sol:16Inheritance: ERC1155Holder
Key Functions
function stake(address account, uint256 nftId, uint256 amount) external;Stakes XPowerNft: transfers nft from account to treasury, mints ppt for account. Calls mty.refreshRates(false). Emits Stake.
function stakeBatch(address account, uint256[] memory nftIds, uint256[] memory amounts) external;Batch stake across multiple NFT IDs.
function unstake(address account, uint256 nftId, uint256 amount) external;Unstakes: burns ppt from account, returns nft from treasury. Calls mty.refreshRates(false). Emits Unstake.
function unstakeBatch(address account, uint256[] memory nftIds, uint256[] memory amounts) external;Batch unstake across multiple NFT IDs.
function approveStake(address operator, bool approved) external;
function approveUnstake(address operator, bool approved) external;
function approvedStake(address account, address operator) public view returns (bool);
function approvedUnstake(address account, address operator) public view returns (bool);Delegation: allows operator to stake/unstake on behalf of caller.
Events
| Event | Parameters |
|---|---|
Stake | address account, uint256 nftId, uint256 amount |
StakeBatch | address account, uint256[] nftIds, uint256[] amounts |
Unstake | address account, uint256 nftId, uint256 amount |
UnstakeBatch | address account, uint256[] nftIds, uint256[] amounts |
ApproveStaking | address indexed account, address indexed operator, bool approved |
ApproveUnstaking | address indexed account, address indexed operator, bool approved |
Custom Errors
| Error | Trigger |
|---|---|
InvalidAmount(uint256 amount) | Zero amount in stake/unstake |
Base Contracts
| Contract | Source | Purpose |
|---|---|---|
NftBase | base/NftBase.sol:17 | Shared ERC1155 base for XPowerNft and APowerNft. Provides NFT ID math (idBy, levelOf, yearOf, denominationOf), supply tracking, and composable URI/royalty/migration support. |
NftMigratable | base/NftMigratable.sol:13 | ERC1155 migration from old v9.x contracts. Supports migrate(), migrateBatch(), seal()/sealAll(), and emigration via migratable(bool). ~4-year deadline. |
NftRoyalty | base/NftRoyalty.sol:13 | EIP-2981 royalty with flat 0.5% rate (price / 200). Beneficiary configurable via setRoyal() by NFT_ROYAL_ROLE. |
URIMalleable | base/URIMalleable.sol:17 | Per-year metadata URIs. Mutable for 10 years after the year, then permanent. Contract-level contractURI() for OpenSea. |
Supervised | base/Supervised.sol:7 | AccessControl base. Defines VERSION, DEFAULT_ADMIN_ROLE, and all sub-roles via abstract supervised contracts. |
Migratable | base/Migratable.sol:17 | ERC20 migration from old contracts. Extended by MoeMigratable and SovMigratable with seal and unit-conversion logic. |
Libraries
| Library | Source | Purpose |
|---|---|---|
Constant | libs/Constant.sol:4 | Time constants (CENTURY, YEAR, MONTH, WEEK, DAY, HOUR, MIN, SEC), DECIMALS = 18, VERSION = 0x10c1. |
Nft | libs/Nft.sol:6 | NFT ID composition/decomposition. idBy(year, level) → 100 * year + level. Requires level % 3 == 0 and level < 100. year() computed from block.timestamp via century math. |
Power | libs/Power.sol:6 | Fractional exponentiation: pow(n * 1e18, exp * 3906250e9) / 1e18. Exponent must be in [128, 512]. |
Polynomials | libs/Polynomials.sol:11 | Polynomial evaluation with power exponentiation. eval3 through eval6 for 4–7 coefficient arrays. |
Integrator | libs/Integrator.sol:8 | Δ-stamp weighted arithmetic mean. Appends (stamp, value) items and computes cumulative area for mean calculation. |
Banq | libs/Banq.sol:12 | Auto-supply to lending pool via banq modifier. Burns excess above claim amount. Enforces MIN_NET2RIP = 100 threshold. |
Rpp | libs/Rpp.sol:9 | Rug-pull protection. Validates parameter arrays (checkArray), rate changes ≤ 2× (checkValue), and minimum 1-month between changes (checkStamp). |
Array | libs/Array.sol:4 | sorted() and unique() array validators used for batch operation input validation. |