Dacade平台SUI Move挑战者合约实践——SUID简单流动性质押池(SUID -Staking Pool Module)
Dacade平台SUI Move挑战者合约实践——SUID简单流动性质押池(SUID-Staking Pool Module)
Dacade平台SUI Move挑战者合约实践——SUID简单流动性质押池(SUID - Staking Pool Module)
rzexin 2024.02.26
1 合约说明
1.1 功能介绍
SUID模块是一个简单的流动性质押池,用户可以质押SUI并获得SUID代币- 用户可以质押
SUI到指定的验证器,或从从指定验证器解除质押
1.2 合约代码
1.2.1 合约源码地址
https://github.com/vijay-kesanakurthi/suid/blob/main/sources/suid.move
1.2.2 数据结构说明
(1)流动性质押池对象
成员变量包括:
- 质押的
SUI代币 - 质押产生的
SUID代币
// Shared pool object
struct Pool has key {
id: UID,
sui: Balance<SUI>,
treasury: TreasuryCap<SUID>,
}
1.2.3 接口说明
(1)初始化方法(init)
- 通过**一次性见证(One Time Witness, OTW)**方式进行初始化,创建
SUID国库 - 并以此创建流动性质押池共享对象
Pool
// custom coin SUID
struct SUID has drop {}
#[allow(unused_function)]
fun init(witness: SUID, ctx: &mut TxContext) {
let (treasury, metadata) = coin::create_currency(
witness,
9,
b"SUID",
b"Dacade Staked SUI",
b"SUID is a Decade Staked SUI",
option::none(),
ctx
);
// Make metadata immutable
transfer::public_freeze_object(metadata);
// Create the shared pool
transfer::share_object(Pool {
id: object::new(ctx),
sui: balance::zero<SUI>(),
treasury,
});
}
(2)添加流动性(add_liquidity_)
- 添加SUI到流动性池中,将1:1得到
SUID作为回报
/*
Entrypoint for the `add_liquidity` method. Sends `SUID` to
the transaction sender.
pool: The shared pool where user want to stake sui.
sui : SUI user want to stake.
*/
entry fun add_liquidity_(
pool: &mut Pool, sui: Coin<SUI>, ctx: &mut TxContext
) {
let liquidity=add_liquidity(pool, sui, ctx);
transfer::public_transfer(liquidity, tx_context::sender(ctx)
);
}
/*
add liquidity to the `Pool` by transfer `SUID`.
pool: The shared pool where user want to stake sui.
sui : SUI user want to stake.
Retrund SUID for given SUI.
*/
public fun add_liquidity(
pool: &mut Pool, sui: Coin<SUI>, ctx: &mut TxContext
): Coin<SUID> {
is_valid_amount(coin::value(&sui));
let sui_balance = coin::into_balance(sui);
let sui_added = balance::value(&sui_balance);
// Increase the supply of SUID
let balance = balance::increase_supply(coin::supply_mut(&mut pool.treasury), sui_added);
balance::join(&mut pool.sui, sui_balance);
coin::from_balance(balance, ctx)
}
// Check if SUI AMount has required value
fun is_valid_amount(amount:u64) {
assert!(amount>= FLOAT_SCALING,EAmountTooLow)
}
(3)移除流动性(remove_liquidity_)
- 从池中移除流动性,将燃烧
SUID代币,并返回质押的SUI
/*
Entrypoint for the `remove_liquidity` method. Transfers
withdrawn assets (SUI) to the sender.
pool: The shared pool where user want to unstake sui.
suid : SUID user want to unstake.
*/
entry fun remove_liquidity_(
pool: &mut Pool,
suid: Coin<SUID>,
ctx: &mut TxContext
) {
let (sui ) = remove_liquidity(pool, suid, ctx);
let sender = tx_context::sender(ctx);
transfer::public_transfer(sui, sender);
}
/*
Remove liquidity from the `Pool` by burning `SUID`.
pool: The shared pool where user want to unstake sui
suid : SUID user want to unstake
Returns `Coin<SUI>`.
*/
public fun remove_liquidity (
pool: &mut Pool,
suid: Coin<SUID>,
ctx: &mut TxContext
): Coin<SUI> {
is_valid_amount(coin::value(&suid));
let suid_amount = coin::value(&suid);
balance::decrease_supply(coin::supply_mut(&mut pool.treasury), coin::into_balance(suid));
coin::take(&mut pool.sui, suid_amount, ctx)
}
(4)质押SUI到指定的验证者(stake)
/*
stake the `SUI` with the given validator.
sui : SUI user want to stake.
state: The state of the SUI system.
validator_address: The address of the validator to stake with.
*/
public fun stake(
sui: Coin<SUI>,
state: &mut SuiSystemState,
validator_address: address,
ctx: &mut TxContext
) {
sui_system::request_add_stake(state, sui, validator_address, ctx);
}
(5)从指定验证者解除质押(unstake)
/*
unstake the `SUI`.
state: The state of the SUI system.
staked_sui: The staked SUI object.
ctx: The transaction context.
*/
public fun unstake(
state: &mut SuiSystemState,
staked_sui: StakedSui,
ctx: &mut TxContext,
) {
sui_system::request_withdraw_stake(
state,
staked_sui,
ctx
);
}
2 前置准备
2.1 帐号准备及角色分配
| 别名 | 地址 | 角色 |
|---|---|---|
| Jason | 0x5c5882d73a6e5b6ea1743fb028eff5e0d7cc8b7ae123d27856c5fe666d91569a |
账号1 |
| Alice | 0x2d178b9704706393d2630fe6cf9415c2c50b181e9e3c7a977237bb2929f82d19 |
账号2 |
| Bob | 0xf2e6ffef7d0543e258d4c47a53d6fa9872de4630cc186950accbd83415b009f0 |
账号3 |
- 将地址添加到环境变量
export JASON=0x5c5882d73a6e5b6ea1743fb028eff5e0d7cc8b7ae123d27856c5fe666d91569a
export ALICE=0x2d178b9704706393d2630fe6cf9415c2c50b181e9e3c7a977237bb2929f82d19
export BOB=0xf2e6ffef7d0543e258d4c47a53d6fa9872de4630cc186950accbd83415b009f0
3 合约部署
切换到Jason账号
sui client publish --gas-budget 100000000
- 命令输出关键信息截图

- 将关键的对象ID记录到环境变量,方便后续调用使用
export PACKAGE_ID=0xdbd3c92e445f176cf8cb2874791d816964615d20da4218530671b625c2978be1
# PACKAGE_ID::suid::Pool
export POOL=0x8913f6eba39d948c7ea2f8a481b4451bf89ab0618662c6323cb5b853bfaefd18
4 合约交互
4.1 添加流动性(add_liquidity_)
export COIN=0x8dea9b14702e1ce63b11d1a2a6f9bc6aaadb91d38cb20b5e0cfa0d93486f206a
sui client call --function add_liquidity_ --package $PACKAGE_ID --module suid --args $POOL $COIN --gas-budget 10000000
- 得到SUID对象
# 0x2::coin::Coin<PACKAGE_ID::suid::SUID>
export SUID=0x15b755334120e2c1a1783bb3b9e616f7dd6a078d548da14e0adfa7299336b211
- 查看SUID对象
sui client object $SUID

4.2 移除流动性(remove_liquidity_)
sui client call --function remove_liquidity_ --package $PACKAGE_ID --module suid --args $POOL $SUID --gas-budget 10000000
- 取回添加的SUI代币
# 0x2::coin::Coin<0x2::sui::SUI>
export COIN2=0xce4d7792ebc78d43e6fd3770be7bd3dfd45b16de2329d269a801c14d858da948
- 查看取回的SUI对象
sui client object $COIN2

4.3 质押SUI到指定的验证者(stake)
export COIN=0x11baf1209cf52ecdea1c283ffa3d96466bbddb99ef23742d81cd89dd12c30a8a # 1SUI
export VALIDATOR_ADDRESS=0x8ffaea5d47a38291e5dd390b6d4c40fd3b1f17864aec217a2f808d8f1ca9b26b # 测试网MoveFunsDAO验证者地址
sui client call --function stake --package $PACKAGE_ID --module suid --args $COIN 0x5 $VALIDATOR_ADDRESS --gas-budget 10000000
- 抛出事件

- 得到
StakedSui对象
export STAKED_SUI=0x53f99cc9a342f619ae79411e0fb622812aabf9f41581962862aa638608f5b2bf

- 查看
StakedSui对象
sui client object $STAKED_SUI

- 通过钱包查看质押对象

4.4 从指定验证者解除质押(unstake)
有些质押解除会报错,不知为何?:
const EStakeWithdrawBeforeActivation: u64 = 6;,Error executing transaction: Failure { error: "MoveAbort(MoveLocation { module: ModuleId { address: 0000000000000000000000000000000000000000000000000000000000000003, name: Identifier(\"sui_system_state_inner\") }, function: 13, instruction: 12, function_name: Some(\"request_withdraw_stake\") }, 6) in command 0", }
sui client call --function unstake --package $PACKAGE_ID --module suid --args 0x5 $STAKED_SUI --gas-budget 10000000
- 抛出事件

- 取回质押的SUI
export UNSTAKED_SUI=0xdfb27566f85ecf3384c443f488053a1f3ad150c8d318c4d566889a054fc6352b
sui client object $UNSTAKED_SUI
