4.1版本比之前的版本增加了交易功能,交易功能的实现基本都是在movescription_to_amm 模块中实现,所以本篇文章我们的重点关注点在movescription_to_amm模块,流动性池,交易等问题。
4.1 版本比之前的版本增加了交易功能,交易功能的实现基本都是在 movescription_to_amm
模块中实现,所以本篇文章我们的重点关注点在 movescription_to_amm
模块,流动性池,交易等问题。
先看 movescription
模块中新增的结构体和函数。这些结构体和函数给交易提供工具和支持
新增的这两个结构体是用于权限管理的。
合约中的交易采用了 Capability
模式。使用了 coin
包
struct Treasury<phantom T> has store{
cap: TreasuryCap<T>,
coin_type: String,
}
struct InitTreasuryArgs<phantom T> has key, store{
id: UID,
tick: String,
cap: Option<TreasuryCap<T>>,
}
先了解一下必须的工具函数,这样有助于后续的业务
movescription_to_coin
函数是将一个铭文销毁,然后返回内部的所有资产
并且,会根据铭文的数量(amount
)来铸币(Balance<T>
)并返回
这个函数主要用于使用铭文添加流动性
public(friend) fun movescription_to_coin<T: drop>(
tick_record: &mut TickRecordV2,
movescription: Movescription
): (Balance<SUI>, Option<Movescription>, Option<Metadata>, Balance<T>)
跟上面的相反,把 balance_t
铸造成铭文.参数中提供的资产全部放进新铸造的铭文中
public(friend) fun coin_to_movescription<T: drop>(
tick_record: &mut TickRecordV2,
acc: Balance<SUI>,
locked: Option<Movescription>,
metadata: Option<Metadata>,
balance_t: Balance<T>,
ctx: &mut TxContext
): (Movescription, Balance<T>)
接下来是本篇的重点,所有的交易函数都在这个合约中实现 流动性池相关的接口,使用了cetus_clmm包,感兴趣的读者可以自行了解
结构体很简单,通过添加动态字段的方式这个结构会放进每种铭文的 TickRecordV2 结构体中,用于记录每个地址添加的流动性
struct Positions has store{
positions: Table<address, Position>,
}
创建一个货币交易市场,需要做的是创建流动性池,添加流动性,以及购买功能,接下来将逐步介绍
public entry fun init_pool<T: drop>(pools: &mut Pools, config: &GlobalConfig, tick_record: &mut TickRecordV2, movescription: Movescription, clk: &Clock, ctx: &mut TxContext)
函数内部使用cetus_clmm::factory::create_pool_with_liquidity<T,SUI>
创建流动性池,并使用参数中的 movescription
添加第一笔流动性
从泛型来看,这是一个 Balance<SUI> 类型的代币和 Balance<T> 的交易池
此后,这个流动性池 position
会被封装进 Positions
结构中,然后放入 tick_record
中,成为这种铭文的流动性池
为一种铭文的池子添加流动性,只能使用这种铭文
public entry fun add_liquidity<T: drop>(
config: &GlobalConfig,
pool: &mut Pool<T,SUI>,
tick_record: &mut TickRecordV2,
movescription: Movescription,
clk: &Clock,
ctx: &mut TxContext)
添加流动性的逻辑是,首先将使用上述的movescription_to_coin
函数将 movescription
销毁,取出其中的资产,得到 Balance<SUI> 、 Balance<T> 两种货币。
之后会向 tick_record
的池子添加流动性并记录在 Positions
的 table 中,对应关系为 address(玩家地址)-->liquidity(此地址的总流动性)
添加流动性需要使用 add_liquidity_with_swap
函数实现:
fun add_liquidity_with_swap<T:drop>(
config: &GlobalConfig,
pool: &mut Pool<T,SUI>,
position_nft: &mut Position,
balance_a: Balance<T>,
balance_b: Balance<SUI>,
clk: &Clock):(Balance<T>, Balance<SUI>)
本函数中逻辑:
1、如果 balance_a/balance_b 值都不为 0,则先使用 add_liquidity_internal
函数添加流动性,将第一次添加完成后剩余的代币取回,此处为了方便,我们称取回的代币也为 balance_a/balance_b
。如果 balance_a/balance_b
其中一个值为 0(假设 balance_a.value = 0),则直接下一步
2、使用 swap
函数将一半 balance_a
兑换成 balance_b
3、再次使用 add_liquidity_internal
函数添加流动性
为池子添加流动性即是添加池子中两种币的总量,要按照此时池子中两种币的比例添加。所以上面的逻辑中需要使用 swap 函数调整两种币的比例
swap 函数中实际上调用了cetus_clmm::pool
中的三个函数实现功能:
pool::flash_swap<CoinTypeA, CoinTypeB>
、
pool::swap_pay_amount(&flash_receipt)
、
pool::repay_flash_swap<CoinTypeA, CoinTypeB>
最终实现添加流动性的函数是 add_liquidity_internal
:
fun add_liquidity_internal<T:drop>(
config: &GlobalConfig,
pool: &mut Pool<T,SUI>,
position_nft: &mut Position,
balance_a: Balance<T>,
balance_b: Balance<SUI>,
clk: &Clock):(Balance<T>, Balance<SUI>, bool)
依旧是掉用cetus_clmm::pool
中的函数pool::add_liquidity()
和pool::repay_add_liquidity()
实现。最终没有用完的代币会全部返回给玩家
移除流动性有两种:按数量移除,或移除一个玩家的所有流动性。分别由两个函数实现: 按数量移除:
public fun do_remove_liquidity<T: drop>(
config: &GlobalConfig,
pool: &mut Pool<T,SUI>,
tick_record: &mut TickRecordV2,
delta_liquidity: u128,
clk: &Clock,
ctx: &mut TxContext) : (Movescription, Balance<T>)
先从 tick_record 中取出玩家添加的流动性(position_nft)对象,然后调用pool::remove_liquidity(config, pool, position_nft, delta_liquidity, clk)
移除 delta_liquidity 数量的流动性。将返回的代币通过上面讲过的movescription::coin_to_movescription
函数重新封装成铭文,返回给玩家
移除一个玩家的所有流动性:
public fun do_remove_all_liquidity<T: drop>(
config: &GlobalConfig,
pool: &mut Pool<T,SUI>,
tick_record: &mut TickRecordV2,
clk: &Clock, ctx: &mut TxContext) : (Movescription, Balance<T>)
和上一个函数逻辑稍有不同,从 tick_record 中取出流动性(position_nft)之后,先获取其总量let liquidity = position::liquidity(position_nft);
,然后再调用pool::remove_liquidity
。
总之,移除流动性会从流动性池中取出玩家的资产,返回给玩家
使用一种币购买另一种币,本质就是交换,所以购买函数“buy”就是调用上面的“swap”函数
swap(config, pool, balance::zero<T>(), coin::into_balance(sui), false, clk)
在 swap 函数中,把买家的币 sui 和 balance::zero<T>()进行互换,然后返回给买家
收取交易费奖励:
public fun do_collect_fee<T: drop>(config: &GlobalConfig, pool: &mut Pool<T,SUI>, tick_record: &mut TickRecordV2, ctx: &mut TxContext) :(Balance<T>, Balance<SUI>)
新版本中重点添加了交易相关的业务逻辑,玩家能够自由交易,也能够将自己的资产放入交易池获取收益。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!