Skip to main content
Staking ALPH mints xALPH, a liquid token whose value in ALPH grows as protocol rewards are deposited. Unstaking burns xALPH and opens an unstake vault that releases the ALPH linearly over unstakeDuration.

Guide: stake and unstake ALPH

Settings

These values mirror the contract parameters. The live values are in getXAlphTokenState() (fields.unstakeDuration, fields.maxActiveUnstakeRequestsPerUser).

xALPH token

getXAlphTokenState()

Useful fields: Exchange rate: 1 xALPH = totalDepositedAlph / totalXAlphSupply ALPH.
getXAlphToken() returns the typed XAlphTokenInstance. getConfig().xAlphTokenId is the xALPH token ID.

Stake

stakeAlph(amount)

Stakes amount attoALPH and mints xALPH to the signer at the current rate. Attaches amount + MINIMAL_CONTRACT_DEPOSIT ALPH. The xALPH token contract is recorded as the referral.

stakeAlphWithReferral(amount, referral)

Same as above, with a custom referral address. The contract does not validate the referral or send it anything. It only records it in the Staked(to, referral, alphAmount, xAlphAmount) event. Partners who want commission on referred stakes must contact the team first.

donateReward(amount)

Deposits amount ALPH as a reward to all xALPH holders without minting xALPH, which raises the exchange rate.

Unstake

Unstaking unlocks linearly. After startUnstake, the claimable ALPH grows with elapsed time, and the full amount is available after unstakeDuration. Call claimUnstaked at any time to withdraw what has unlocked so far.

startUnstake(amount)

Burns amount xALPH and creates a new unstake vault for the signer, holding the equivalent ALPH. Each user can hold at most maxActiveUnstakeRequestsPerUser active vaults.

getActiveUnstakeVaultIndexes(address)

Returns bigint[] with the vault indexes of the user’s pending or claimable requests.

getAlphUnstakeVaultState(address, vaultIndex)

Claimable ALPH is totalUnstakeAmount × min(elapsed, unstakeDuration) / unstakeDuration − withdrawnAmount, so a request is fully unlocked at unstakeStartTime + unstakeDuration. getAlphUnstakeVault(address, vaultIndex) returns the typed contract instance.

getClaimableAmount(address, vaultIndex)

ALPH currently claimable from a vault. It grows linearly from 0n when the request starts.

claimUnstaked(vaultIndex, amount)

Withdraws amount ALPH from the vault to the signer. amount must be greater than 0 and at most the claimable amount.

cancelUnstake(vaultIndex)

Closes a request. ALPH that has already unlocked is sent to the signer, and the rest is re-staked and returned as xALPH at the current rate. The UnstakeCancelled event reports xAlphAmount, claimedAlphAmount, and restakedAlphAmount.

How rewards reach xALPH

Protocol fees from CPMM and CLMM pools flow into the RewardFeeCollector. The Powfi team collects them and converts them to ALPH. Then distributeRewards pays out totalDepositedAlph × rewardRate / 10000 × elapsed / 1 year (an annual rate), capped by the ALPH the collector holds. The treasury share is taken first, a burn share is taken from what remains, and the rest is deposited into xALPH, which raises the exchange rate. distributeRewards is not restricted, and nothing calls it automatically. Apart from donateReward, which raises the rate immediately, the xALPH rate only rises when someone calls it.

Other accessors

Helpers

decodeU256List(hex) and decodeContractIdList(hex) decode the packed byte-vector returns used by the staking contracts (32-byte chunks).