Stride's Technical Architecture
A technical overview of how Stride enabled interchain liquid staking.
High-Level System Design
Users stake their tokens on Stride from any Cosmos chain. Rewards accumulate in real time. No minimum. They will receive staked tokens immediately when they liquid stake. These staked tokens can be freely traded, and can be redeemed with Stride at any time to receive your original tokens plus staking rewards.
On the backend, Stride permissionlessly stakes these tokens on the host chain and compounds user rewards. Stride lets users use your staked tokens to compound their yields. Continue to earn staking yield, and earn additional yield by lending, LPing, and more. They can set their own risk tolerance in Cosmos DeFi.
Users can always redeem from Stride. When they select "redeeem" on the Stride website, Stride will initiate unbonding on the host zone. Once the unbonding period elapses, the users will receive native tokens in their wallets.
In-Depth System Design
*Written by the wonderful Informal Systems audit team.
In Stride, staking occurs every 6 hours and it goes through 3 epochs:
- epoch n: New deposit record (DR) which tracks all deposits in a given epoch for a given host zone is created with 0 tokens. LiquidStake is called then and stTokens are minted, but the actual staking of the user’s tokens is addressed in epoch n+2.
- epoch n+1: All tokens on DR from epoch n are IBC transferred from Stride’s module account to Delegation ICA. Whenever a change to delegation happens all of the rewards are withdrawn (to Withdraw ICA). • epoch n+2: Tokens on the DR are staked (by weight) across all (30 at the moment) Stride validators.
Reinvestment executes automatically and the rewards are auto-compounded on every epoch (6h). 90% of the rewards are being sent to Delegation ICA (reinvestment) and 10% to the Fee ICA (the only place where Stride charges the fees)
- epoch n: Queries Interchain Query (ICQ) to check balances of Withdraw ICA and creates a new record for those tokens.
- epoch n+1: Transfers tokens to Delegation ICA from the Withdraw ICA.
- epoch n+2: Stakes the tokens.
Unstaking executes every day. Only 7 concurrent unbondings are allowed (a constraint on Cosmos) on host zones for a delegator and validator pair.
- epoch n: EpochUnbondingRecord is created. It stores many HostZoneUnbondings (HZU), with one HZU per host zone (e.g. for CosmosHub we have 1 HZU per epoch). When the user sends 1stAtom to Stride (Stride now custodies this 1 stAtom) and specifies an address on the Cosmos Hub that the tokens should be sent, HZU is updated and UserRedemptionRecord (URR) is created (claim on user’s tokens that they can trigger later once the tokens have unbonded).
- epoch n+m (m = unbondingPeriodOnHostZone / 7 + 1): For CosmosHub it happens every 4 days (unbPeriod = 21 days). MsgUndelegate is triggered and all of the pulled unbonding tokens are undelegated (MsgUndelegate ICAs are triggered across the validators Stride has delegated to). HZUs are updated with unbonding time.
- epoch n+unbonding time: Tokens are transferred to Redemption ICA account. The URR is updated so that the tokens are claimable and anyone can transfer tokens to the already specified address which is stored on URR. So this is an ICA call that transfers tokens back to the end user’s account.
Deposit & Liquid Staking
Withdrawal and deposit belong to regular bank transfers (outside of Stride). After transferring native tokens to Stride, liquid staking can be processed and it includes:
- Sending IBC/Tokens to stakeibc account
- Minting stTokens to stakeibc account
- Sending stTokens from stakeibc account to user account on Stride
Staking & Reinvesment
Staking and reinvestment steps:
- Sweeps the deposit record (DR) marked
TRANSFER_QUEUE
from previous epochs. Under the hub, it con structs IBCMsgTransfer
with 30min timeout.TransferCallback
is also created which is been calledOnAcknowledgementPacket
orOnTimeoutPacket
. In the case of nill ack or ack_error DR’s status is set back toTRANSFER_QUEUE
otherwise it becomes a candidate for delegation withDELEGATION_QUEUE
flag. - Delegates DRs with status
DELEGATION_QUEUE
. It creates a set ofMsgDelegate
msgs (delegation to every validator from that host zone whose relative amount is positive). Each validator getstargetAmount=valWeight*depRecordAmount / totalValWeight
. Also,DelegateCallback
is defined. In the case of the happy ibc path, the zone’s staked balance is increased by a delegated amount to each validator whosedelegationAmt
is updated and finally DR is removed. - Rewards are automatically sent to the Withdrawal ICA.
WithdrawalBalanceCallback
executes ICASendTx
withMsgSend
to Delegation ICA (90% reward) and Fee ICA (10% reward). It also addsReinvestCallback
which triggers as previous ones, and in the happy path, it creates a new DR withDELEGATION_QUEUE
status (usingWITHDRAWAL_ICA
source this time, not STRIDE source) while the sad path is ignored.
Unbonding
Unbonding goes as follows:
- User sends
RedeemStake
msg which createsUserRedemptionRecord
(URR), calculates the amount of native tokens to get back:nativeAmount=stAmount*redemptionRate
, updates HostZoneUnbonding (HZU) record and sends numStAtoms to module’s account where they will eventually be burned after unbonding. - On every epoch (a day) initiates unbondings for all host zones with ICA
SendTx
containingMsgUndelegate
(from Delegation ICA to all validators) and sets HZU status toUNBONDING_IN_PROGRESS
(note: HZU is created atRegisterHostZone
with initial status set toUNBONDING_QUEUE
). If ICA SendTx fails,UndelegateCallback
will roll back the HZU status toUNBONDING_QUEUE
, otherwise it burns escrowed stTokens, updates: HZU status toEXIT_TRANSFER_QUEUE
, HostZone staked balance and validator amounts. - The funds are in escrow for the unbonding period and then get automatically transferred to back to the Delegation ICA.
- Once per epoch if the unbonding period has elapsed, all HZU’s tokens with
EXIT_TRANSFER_QUEUE
are swept as a batch to Redemption ICA. If everything goes well, HZU status is set toCLAIMABLE
, otherwise it’s reset toEXIT_TRANSFER_QUEUE
duringRedemptionCallback
execution. - Users can claim their unbonded tokes via
ClaimUndelegatedToken
which also sets claim pending to TRUE (to avoid double claims). ICASendTx
is constructed withMsgSend
inside (from Redemption ICA to user address on host) with 10min timeout. If no ack errors, URR is removed and HZU’s native token amount is decremented by the claimed value. Else, if timeot or ack failure, claim pending is set to false.
Interchain Accounts
It can be seen that many paths lead to ICA’s SendTx
, including both staking and unstaking, while all paths (except direct Msgs) have the same root - the BeforeEpochStart
function.
There are only two scenarios for ICA’s RegisterInterchainAccount
to be called. The first one is when registering the host zone, 4 ICAs are created. The second one, in the case of timeout, if a channel closes, the controller chain must be able to regain access to registered interchain accounts by simply opening a new channel which is done through RestoreInterchainAccount
. IBCTransfer
is called at one place only from record’s module when sweeping existing deposits from Stride to the Host Zones.
Updated 2 months ago