Solana
Jito's Restaking Framework
Jito's Restaking Framework

On July 26th, Jito made its restaking code open-source on GitHub, making a pretty spectacular move for the blockchain space. The repository is available at Jito Foundation's GitHub and gives a lot of insight into what Jito envisions exactly in their restaking paradigm. At that, while the release repository is primarily an implementation at the interface level, it sheds some light on the fundamentals underpinning Jito's restaking framework. In this article, we would like to continue with expanding the concept of restaking in Jito and mention how exactly such an approach might have further development consequences.

Restaking Ecosystem Components

  • Operator: Operates a node to execute AVS and earn rewards from it.
  • AVS (Actively Validated Service): A service that leverages the economic security of staked or restaked tokens. Such services include oracles, bridges, and hybrid exchanges.
  • Vault: The staker stakes tokens into the vault and receives new tokens that specify their share of the vault. A holder delegating their staked tokens to an operator or AVS for economic security would implicate those tokens in the vault and could be slashed for an operator's misbehavior. The operator or AVS to which the vault delegated tokens may reward the stakers.
  • Slasher : Tracks the activities of node operators and slashes tokens if an operator misbehaves. Slashed tokens go to the slasher, providing an incentive to find misbehavior.
  • Token Staker: A user of the restaking program who wants to maximize yield by letting his or her tokens be redeployed in AVS. Stakers stake their tokens into the vault, and the vault delegates these tokens on behalf of the stakers.

Jito Restaking : Permissionless and Super Flexible

Vault Program

Jito's restaking system is structured to underpin all SPL tokens and offer staking and utility functions based on it. At the heart of this system lies the vault program, which is solely responsible for the creation and management of vaults. Anyone can create a vault, and upon staking assets in the vault, receive tokens in return. Here are some key points about the vault program:

  • Building and Managing Vaults: Anyone can create a vault, upon staking assets, tokens are issued to represent the staked amount.
  • Token Support: The program, though represented by lrt_mint, can generally deposit SPL 20 tokens directly.
    • Anyone can make vault with tokens from wSol to Bonk
  • Migration Support: ItializeVaultWithMint feature facilitates easy migration for tokens with existing staking systems.
    • Tokens that previously had their own staking systems can migrate their vault to the Jito vault program. This allows them to use their tokens to secure the AVS, providing token holders with the opportunity to earn additional rewards.
  • Vault Components: The vault contains the base public key, lrt_mint, supported mint address, admin public keys, and a lot of other important information.

Vault Struct

So here is a sample definition of the vault struct in code:

#[derive(Debug, Clone, Copy, PartialEq, BorshDeserialize, BorshSerialize)]
pub struct Vault {
    account_type: AccountType,
    base: Pubkey,
    lrt_mint: Pubkey,
    supported_mint: Pubkey,
    admin: Pubkey,
    delegation_admin: Pubkey,
    operator_admin: Pubkey,
    avs_admin: Pubkey,
    slasher_admin: Pubkey,
    fee_owner: Pubkey,
    mint_burn_authority: Pubkey,
    capacity: u64,
    vault_index: u64,
    lrt_supply: u64,
    tokens_deposited: u64,
    deposit_fee_bps: u16,
    withdrawal_fee_bps: u16,
    avs_count: u64,
    operator_count: u64,
    slasher_count: u64,
    reserved: [u8; 128],
    bump: u8,
}

This comes structured details around the vault: all the various admin roles for managing delegations, operators, AVS (Actively Validated Services) and slashing, fees, and capacities.

Explanation of Vault Struct

The Vault struct lies at the heart of the restaking framework by Jito. Let's break it down:

  • Base: Public key used as a seed for deriving the vault address.
  • lrt_mint: This is the mint address for the Liquid Restaking Token (LRT) that users get when they stake their assets in the vault.
  • supported_mint: This is the mint address of the token that the vault supports for staking.
  • Admin Roles: Defines different admin roles to maintain different sections of the vault including delegations, operators, AVS, and slashing. Each role is designated with unique permissions for carrying out activity on the vault in an organized and secure manner.
  • Fee Structure: The vault also features fields for deposit and withdrawal fees. These are expressed as basis points (bps).
  • Capacity: It specifies the maximum quantity of tokens that the vault can take.
  • Vault Index and Counts: These fields are useful for identifying the vault within the program and counting the number of associated AVS, operators, and slashing events.

Restaking Program

The restaking program in Jito's framework offers a way to construct and manage AVS and operators. In both cases, the AVS and operators can opt into each other and receive delegations from vaults. It's a program that manages the bidirectional opt-in process where there is operator signaling of interest to participate in an AVS which does the opting in. The same happens with vaults.

AVS Struct

Let's take a look at the structure of AVS:

#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)]
#[repr(C)]
pub struct Avs {
    account_type: AccountType,
    base: Pubkey,
    admin: Pubkey,
    operator_admin: Pubkey,
    vault_admin: Pubkey,
    slasher_admin: Pubkey,
    withdraw_admin: Pubkey,
    index: u64,
    operator_count: u64,
    vault_count: u64,
    slasher_count: u64,
    reserved: [u8; 128],
    bump: u8,
}

Such details include the base public key, administrative roles, operators, vaults, slashers count, and reserved space for future expansion.

AVS Struct Explanation

The Avs struct is to handle AVS(Actively Validated Services) within the Jito ecosystem. Critical members include:

  • Base: This is the public key from which the AVS address is to be generated.
  • Admin Roles: The AVS structure comprises different admin roles that hold given permissions specifically on the management of operators, vaults, and slashing events.
  • Index and Counts: The index field states the identification of the AVS within the restaking program, while the count fields list counts of operators, vaults, and slashing events related to the AVS.

Opt-In Mechanism

The opt-in mechanism in the Jito restaking framework is one that enables seamless and secure participation for other different entities in the staking ecosystem on-chain. The mechanism allows both vaults and AVS, as well as operators, to make bi-directional agreements on participation and interaction.

Opt-in Process for Operators and AVS

  1. Operator Signals Intent: An operator wanting to avail an AVS signals on-chain, by creating a operator_avs_ticket.
  2. AVS Opts In: The AVS will be enabled to turn its attention to the signal and opt in by acknowledging the avs_operator_ticket.
  3. Mutual Agreement: There must exist some form of agreement between the operator and the AVS toward the act of participation. This mutual agreement ensures that only entities that are supposed to interact with one another and use each other's resources do so.

Opt-In Process for Vaults and AVS

  1. Vault Signals Intent: A vault interested in delegating assets to an AVS creates a vault_avs_ticket.
  2. AVS Opts In: The AVS processes the signal and opts in by sending back an acknowledgement of the avs_vault_ticket.
  3. Setup the Delegation: The delegation is set up once the AVS and the vault agree to allow the AVS to start handling the vault's staked assets.

Opt-In Process for Vaults and Operators

  1. Vault Signals Intent: A vault signals its intent to work with an operator by creating an vault_operator_ticket.
  2. Operator Opts In: The operator examines the ticket and opts in through an acknowledgment of the operator_vault_ticket.
  3. Resource Allocation: The vault can delegate its resources, by mutual agreement, to the operator for and on behalf of staking or any other activity.

This is the very mechanism that forms the basis for a secure, flexible staking ecosystem with the ability to allow entities to selectively engage and collaborate on the basis of mutual consent.

Slashing & Rewards

The other critical element in Jito's restaking design is the slashing mechanism. Although the code does not clarify how the AVS distributes rewards to the stakers of the vault, it does detail the procedure for slashing. For each epoch, there is an upper limit on the number of slashable acts that may be committed to the AVS at any vault. Within this limit, slashing ensures that operator misbehavior is punished by deducting the slashed amount from the operator's allocation. Once operators receive delegation from the vault, the corresponding slashed amounts are transferred from the vault to the slasher.

Process/Slash function

The process_slash is the main function within the slashing mechanism.

pub fn process_slash(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    slash_amount: u64,
) -> ProgramResult {
    let slot = Clock::get()?.slot;
    let SanitizedAccounts {
        mut vault,
        operator,
        avs_operator_ticket,
        operator_avs_ticket,
        avs_vault_ticket,
        operator_vault_ticket,
        vault_avs_ticket,
        vault_operator_ticket,
        avs_vault_slasher_ticket,
        vault_avs_slasher_ticket,
        mut vault_delegation_list,
        mut vault_avs_slasher_operator_ticket,
        mut vault_token_account,
        slasher_token_account,
    } = SanitizedAccounts::sanitize(program_id, accounts, slot)?;

    vault_avs_ticket.vault_avs_ticket().check_active(slot)?;
    avs_vault_ticket.avs_vault_ticket().check_active(slot)?;
    operator_vault_ticket.operator_vault_ticket().check_active(slot)?;
    vault_operator_ticket.vault_operator_ticket().check_active(slot)?;
    avs_operator_ticket.avs_operator_ticket().check_active(slot)?;
    operator_avs_ticket.operator_avs_ticket().check_active(slot)?;
    avs_vault_slasher_ticket.avs_vault_slasher_ticket().check_active(slot)?;
    vault_avs_slasher_ticket.vault_avs_slasher_ticket().check_active(slot)?;

    let max_slashable_per_epoch = vault_avs_slasher_ticket.vault_avs_slasher_ticket().max_slashable_per_epoch();
    vault_avs_slasher_operator_ticket.vault_avs_slasher_operator_ticket().check_max_slashable_not_exceeded(slash_amount, max_slashable_per_epoch)?;

    vault_delegation_list.vault_delegation_list_mut().slash(operator.account().key, slash_amount)?;

    vault_avs_slasher_operator_ticket.vault_avs_slasher_operator_ticket_mut().increment_slashed_amount(slash_amount)?;

    _transfer_slashed_funds(
        &vault,
        &vault_token_account,
        &slasher_token_account,
        slash_amount,
    )?;

    vault_token_account.reload()?;
    vault.vault_mut().set_tokens_deposited(vault_token_account.token_account().amount);

    vault.save()?;
    vault_delegation_list.save()?;
    vault_avs_slasher_operator_ticket.save()?;

    Ok(())
}

This function manages the slashing process: It checks the opt-in status of vaults, operators, and AVS against the maximum limit of slashing and then transfers the amount slashed from the vault to the slasher.

  1. Account Sanitization: This will help ensure that all accounts involved are live and valid.
  2. Check Opt-in Status: Guarantees the vault, AVS, and all operators have, in fact, opted into one another.
  3. Check Slash Limits: The checking that the quantity of slashing stays under the maximum slashable for this epoch.
  4. Execute Slash: Reduces the slashed amount from the operator's stake and updates the delegation list.
  5. Transfer Funds: Transfer the funds of the slashed tokens from the vault to the account of the slasher.

Vault Delegation List

The VaultDelegationList struct and its slash method are essential for managing operator delegations and implementing slashing:

#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)]
pub struct VaultDelegationList {
    /// The account type
    account_type: AccountType,

    /// The vault this operator list is associated with
    vault: Pubkey,

    /// the list of delegations
    delegations: Vec<OperatorDelegation>,

    /// The last slot the operator list was updated.
    /// Delegation information here is out of date if the last update epoch < current epoch
    last_slot_updated: u64,

    /// Reserved space
    reserved: [u8; 128],

    /// The bump seed for the PDA
    bump: u8,
}

// method of VaultDelegationList
pub fn slash(&mut self, operator: &Pubkey, slash_amount: u64) -> VaultCoreResult<()> {
    if let Some(operator) = self
        .delegations
        .iter_mut()
        .find(|x| x.operator == *operator)
    {
        let total_staked_amount = operator
            .active_amount
            .checked_add(operator.cooling_down_amount)
            .ok_or(VaultCoreError::VaultSlashingOverflow)?;

        let active_slash_amount = operator
            .active_amount
            .checked_mul(slash_amount)
            .ok_or(VaultCoreError::VaultSlashingOverflow)?
            .checked_div(total_staked_amount)
            .unwrap_or(0);

        msg!(
            "slashing {} from active, {} from cooling down",
            active_slash_amount,
            slash_amount
                .checked_sub(active_slash_amount)
                .unwrap_or(99999999999999)
        );
        let cooling_down_slash_amount = slash_amount
            .checked_sub(active_slash_amount)
            .ok_or(VaultCoreError::VaultSlashingUnderflow)?;

        operator.active_amount = operator
            .active_amount
            .checked_sub(active_slash_amount)
            .ok_or(VaultCoreError::VaultSlashingUnderflow)?;
        operator.cooling_down_amount = operator
            .cooling_down_amount
            .checked_sub(cooling_down_slash_amount)
            .ok_or(VaultCoreError::VaultSlashingUnderflow)?;

        Ok(())
    } else {
        Err(VaultCoreError::VaultOperatorNotFound)
    }
}

This implementation will ensure that the slashed amounts are deducted from both active and cooling-down stakes, maintaining correctness regarding the total staked assets in the vault.

New Use Case for JTO Tokens

The configuration of the restaking and vault programs once initiated cannot be set up again, with an admin having control over them. As for the fact that it would be the Jito team deploying the program, there are high chances they would hold the admin key to manage the operations. While there are no network-directed parameters in the current configuration, reserved spaces might introduce parameters that dramatically impact the entire ecosystem later on.

Such changes of parameters or modifications in the structure of the programs could also be controlled via JTO tokens, suggesting still another utility of the token. This would put JTO tokens not only in a way of more empowerment but at the center of the whole infrastructural ecosystem, from Solana staking to liquid staking and restaking.

Conclusion

The restaking framework by Jito is quite a pioneering activity in the blockchain ecosystem: flexible, permissionless, and open-source for staking and restaking SPL tokens. The code for restaking has been open-sourced, letting people peer deep into Jito's vision and setting the stage for future development that could change the face of staking. With the potential to have governance applications with the JTO tokens, the Jito framework could be core blockchain infrastructure, which will spur innovation and grow more use cases in the ecosystem.

Go back