Sui Move Bucket 稳定币协议合约初探

  • justin
  • 更新于 2024-08-22 18:54
  • 阅读 665

SuiMoveBucket稳定币协议合约初探Bucket协议SUI上的基于抵押资产的稳定币协议,通过抵押SUI等加密资产,用户可以借出对应的稳定币BUCK核心组件Bucket协议中有不少名字有趣的核心组件,它们有这样的关系图表Bucket可以理解为桶是一个容器,它管理着同类

前言

Bucket 协议是SUI上的基于抵押资产的稳定币协议,通过抵押SUI等加密资产,用户可以借出对应的稳定币 BUCK

核心组件

Bucket 协议中有不少名字有趣的核心组件,它们有这样的关系图表

bucket-protocol.png

Bucket

可以理解为 是一个容器,它管理着同类抵押资产的所有参与者的信息

Move定义

public struct Bucket<phantom T0> has store, key {
    id: sui::object::UID,
    min_collateral_ratio: u64,
    recovery_mode_threshold: u64,
    collateral_decimal: u8,
    max_mint_amount: std::option::Option<u64>,
    collateral_vault: sui::balance::Balance<T0>,
    bottle_table: bucket_protocol::bottle::BottleTable,
    surplus_bottle_table: sui::table::Table<address, bucket_protocol::bottle::Bottle>,
    minted_buck_amount: u64,
    base_fee_rate: u64,
    latest_redemption_time: u64,
    total_flash_loan_amount: u64,
}

T0:抵押的加密货币的类型,比如 0x2::sui::SUI collateral_vault: 抵押金库,所有同类抵押品的balance总和 bottle_table: 抵押参与者的数据结构,该结构有一个核心的字段table 它是基于抵押率排序的链表,在后面的redeem操作中会优先处理抵押率较低的bottle来进行基于抵押物实际价值的赎回操作 surplus_bottle_table:赎回redeem操作中如果一个bottle被完全赎回销毁了,就会自动创建一个盈余table,下一次对该bottle的借贷过程中会尝试从盈余table拿回剩下的抵押物

Bottle

可以理解为瓶子 它代表每个参与者的抵押借贷信息

Move定义

public struct Bottle has store, key {
    id: UID,
    collateral_amount: u64,
    buck_amount: u64,
    stake_amount: u64,
    reward_coll_snapshot: u128,
    reward_debt_snapshot: u128,
}

collateral_amount:抵押品的数量 buck_amount:借出来的buck数量

Tank

可以理解为 蓄水池,它在清算流程中有着重要的作用 当一个用户的bottle因为健康值低于110%被清算的时候,首先会通过Tank里的Buck来偿还清算,然后Tank会收到bottle的打折抵押物 用户也可以通过手动存入buck到tank中得到代币ContributorToken,根据持有的ContributorToken占比可以获得bottle清算的抵押物作为奖励

Well

可以理解为 福利池,协议中的各种fee都会在well中进行收集,比如Borrow(抵押借贷), Redeem(赎回), Flash Loan(闪电贷), Liquidation(清算)

public struct Well<phantom T0> has store, key {
    id: UID,
    shared_pool: Balance<T0>,
    reserve: Balance<T0>,
    staked: Balance<BKT>,
    total_weight: u64,
    current_s: u128,
}

核心操作

borrow

抵押借贷,用户通过存入抵押的加密货币,来借出一定数量的BUCK稳定币 collateralInput 就是存入抵押的加密货币的balance值
buckMintAmount 是你期望借出的buck数量 只要满足存入抵押物之后bottle还满足健康条件都能借出来 insertionPlace bottle的管理是用了一个基于抵押率排序的LinkedTable,所以这里的插入位置其实是一个建议值,可以减少遍历链表所产生的gas费,不传的话就是从链表的front开始遍历

public fun borrow<T0>(
    protocol: &mut BucketProtocol,
    oracle: &BucketOracle,
    clock: &Clock,
    collateralInput: Balance<T0>,
    buckMintAmount: u64,
    insertionPlace: Option<address>,
    ctx: &mut TxContext
) : Balance<BUCK> {
}

repay

偿还操作,用户通过偿还buck来换回它之前存入bottle的抵押加密货币 该操作和下面的redeem有所不同,它只能由用户自己来偿还,同时它是不考虑偿还时候的抵押物的实际价值的,而是根据buck和抵押物的比例来偿还

public fun repay<T0>(
    bucketProtocol: &mut BucketProtocol,
    buckInput: Balance<BUCK>,
    ctx: &TxContext
) : Balance<T0> {
}

redeem

赎回操作,它是维持BUCK稳定币锚定1美元地板价格的方式 任何持有BUCK的用户都可以通过赎回操作来换取协议里存入的抵押加密货币 赎回的时候,会使用Bucket里的BottleTable数据结构,根据抵押率从低到高进行赎回

public fun redeem<T0>(
    bucketProtocol: &mut BucketProtocol,
    oracle: &BucketOracle,
    clock: &Clock,
    buckInput: Balance<BUCK>,
    insertionPlace: Option<address>
) : Balance<T0> {
}

liquidate

清算操作,当一个bottle的抵押率低于110%的时候,它就可以被清算 Bucket协议清算的时候设计了Tank缓冲池来作为偿还BUCK获得抵押物的第一来源

public fun liquidate_under_normal_mode<T0>(
    bucketProtocol: &mut BucketProtocol, 
    oracle: &BucketOracle, 
    clock: &Clock, 
    targetAddress: address
) : Balance<T0> {
}

flash loan

闪电贷,在MOVE中通过hot potato模式就可以实现闪电贷 在Bucket协议中,闪电贷的池子来源有两处

一处是bottle中的抵押物

public fun flash_borrow<T0>(
    bucketProtocol: &mut BucketProtocol, 
    amount: u64
) : (Balance<T0>, bucket::FlashReceipt<T0>) {
}
public fun flash_repay<T0>(
    bucketProtocol: &mut BucketProtocol, 
    repayBalance: Balance<T0>, 
    flashReceipt: bucket::FlashReceipt<T0>
) {
}

一处是tank中存入的buck

public fun flash_borrow_buck<T0>(
    bucketProtocol: &mut BucketProtocol, 
    amount: u64
) : (Balance<BUCK>, tank::FlashReceipt<BUCK, T0>) {
}
public fun flash_repay_buck<T0>(
    bucketProtocol: &mut BucketProtocol, 
    repayBalance: Balance<BUCK>, 
    flashReceipt: tank::FlashReceipt<BUCK, T0>
) {
}

bucket::FlashReceipt和tank::FlashReceipt分别是实现闪电贷所用的hot potato凭据,拿到凭据后必须在同一个PTB中完成借款资金的归还

PSM模块

Buck锚定在1美元,之前的方法是通过鼓励套利者通过borrow/redeem操作来完成的 PSM模块则是提供了另外一种更简单便捷的方法,也即通过维护Buck和USDT/USDC的池子

如果BUCK高于1 USDC,用户可以以1:1的价格将USDC兑换成BUCK,然后卖出BUCK获利。 在市场激励的推动下,这给BUCK带来了抛售压力,引导BUCK的价格回到1美元。

如果BUCK低于1 USDC,用户可以购买BUCK并通过PSM转换为USDC。 这种购买压力对用户来说是有利可图的,通过增加对BUCK的需求,有助于重建BUCK与USDC/USDT的锚定。

PSM合约模块实现也比较简单,Buck和池子里的USDC/USDT是一比一兑换的

public struct Reservoir<phantom T0> has store, key {
    id: sui::object::UID,
    conversion_rate: u64,
    charge_fee_rate: u64,
    discharge_fee_rate: u64,
    pool: sui::balance::Balance<T0>,
    buck_minted_amount: u64,
}
public(friend) fun handle_charge<T0>(
    reservoir: &mut Reservoir<T0>,
    chargeBalance: sui::balance::Balance<T0>
) : u64 {
}
public(friend) fun handle_discharge<T0>(
    reservoir: &mut Reservoir<T0>, 
    amount: u64
) : sui::balance::Balance<T0> {
}

总结

本文通过分析Bucket Move合约,介绍了协议里相关组件和模块,Bucket是一个超额抵押稳定币协议,具有创新的清算和赎回机制 此外,Bucket协议从一开始就设计了不少激励用户的机制,将其协议收入的很大一部分代币化并重新分配给用户。 当然,Bucket协议里还设计了其他机制,比如Recovery Mode,借贷buck时候的复利计算Interest Rate,Tank池子空的时候保底机制redistribution,这些都可以通过下面的参考资料进一步的学习

参考资料

bucket官方文档 bucket白皮书 bucket SDK

点赞 1
收藏 2
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
justin
justin
Move Newbie