This is a guide for building a liquid staking contract in CosmWasm for Sei protocol
_liquid staking_
is a contract for you to delegate and bond your native tokens to earn staking rewards without losing access to your funds.
We need a cw20
token contract to represent our staked native token. Staking contract will be the minter of this token.
In this guide, we will learn more about how to write, deploy and interact with liquid staking contract.
We create a new project using CosmWasm Starter Pack Template to initiate our contract.
$ cargo generate --git <https://github.com/CosmWasm/cw-template.git> --name LIQUID_STAKING
Go inside the project directory, we edit the Cargo.toml
file as below to add dependencies for our contract:
[dependencies]
cosmwasm-std = { version = “1.0.0-beta8”, features = [“staking”] }
cosmwasm-storage = “1.0.0-beta5”
cw-storage-plus = “0.12”
cw20 = “0.13.2”
…
The staking
feature is added to cosmwasm-std
to include staking module to our contract. We also use cw20
here to get a lot of helpers for interacting with cw20
contract.
Linked-list storage
We need a linked-list in our contract to crease an unstaking queue. Each node of the linked-list will contain an unstaking request.The reason we use linked-list in our code is for unstaker to not wait full 21 days to undelegate his token. The native tokens of those who want to stake will be sent to unstakers in unstaking queue, thus making unstaking process much more faster.
To create linked-list storage, we use 2 available storages:
To save basic information of the link-list, we will use Singleton
. For this storage to work, we create LinkedList
struct that contains all the vars we want to put inside the storage. To load and save data inside the storage in a transaction, we create the linked_list
function. We also create a linked_list_read
function to read data in a query:
// file src/linked_list.rs
use cosmwasm_std::{Storage,};
use cosmwasm_storage::{
singleton, singleton_read, ReadonlySingleton,
Singleton,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
static LINKED_LIST_KEY: &[u8] = b"linked_list";
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct LinkedList {
pub head_id: u64,
pub tail_id: u64,
pub length: u64,
}
pub fn linked_list(storage: &mut dyn Storage) -> Singleton<LinkedList> {
singleton(storage, LINKED_LIST_KEY)
}
pub fn linked_list_read(storage: &dyn Storage) -> ReadonlySingleton<LinkedList> {
singleton_read(storage, LINKED_LIST_KEY)
}