Salty WalkThrough
Github: https://github.com/code-423n4/2024-01-salty
Documentation: https://tech.salty.io/
Overview
主要分为几个模块:
- AMM:涉及pool底层swap及arbitrage
- DAO:涉及proposal rewards liquidity分配处理
- Stable:利用lp的底层资产实现的稳定币机制
- Stake:抵押salt获得xsalt
- Rewards:利润分红模块
- Lauch:启动空投 激励模块

启动
相关逻辑位于Lauch目录
- 链下权限校验通过的用户可以提交签名来投票,等投票结果
- 投票通过后触发salt的分配
- 52m→emissions
- 25m→dao
- 10m→dev
- 5m→airdrop
- 5m→lp rewards
- 3m→stake rewards
LP
相关逻辑位于Stable目录
负责提供抵押物池的collateral LP:
depositCollateralAndIncreaseShare:转入wbtc weth获得shareswithdrawCollateralAndClaim:提取流动性,拿回wbtc wethborrowUSDS:根据shares作为抵押物,mint出usdsrepayUSDS:偿还usds,把收到的usds发到liquidizer合约,负责销毁
由于存在杠杆,lp的借贷可以被清算:
liquidateUser:移除被清算人的流动性,移除份额shares- 取回的wbtc weth按比例分红给清算人和liquidizer
- 把用户借出的usds全部给liquidizer
其他whitelist pool的lp:
depositLiquidityAndIncreaseShare:转入token a b获得shareswithdrawLiquidityAndClaim:提取流动性,拿回token a b
Staker
相关逻辑位于Staking目录
- 通过
stakeSALT来质押salt,获取份额shares unstake取消质押,减掉份额recoverSALT取回质押的salt
Trader
相关逻辑位于AMM目录
- 可以通过
deposit和withdrawt,提前预存款在合约内用于swap - 通过
swap,depositSwapWithdraw,depositDoubleSwapWithdraw进行swap- swap过程中分析是否存在套利利润,如果有则自动执行,并将利润更新到dao的账上
DAO
相关逻辑位于DAO目录
首先是提案权力:
- 分几类:修改协议参数,控制代币白名单,地域黑名单,salt的分配,合约的调用,修改网站信息等
什么人有权提案?
- dao地址
- 是否持有足够的xSALT(质押salt所得)
议案流程
- DAO提出议案
- 用户再对议案投票:质押得到多少shares就能对议案投多少票
- 若议案通过,可以调用
finalizeBallot执行
除了议案投票,dao也在协议中持有流动性和分红
formPOL:由upkeep调用,向抵押物池子提供流动性,获得shareswithdrawPOL:由liquidizer调用,按照比例提取流动性,再将所得发送到liquidizerwithdrawArbitrageProfits:由upkeep调用,提取出套利利润,再发送给upkeepprocessRewardsFromPOL:由upkeep调用- 从usds/salt usds/dai两个池子中获取分红,转移10%salt给团队,剩下的50%发送到usds合约burn掉
Reward
reward的链路源头是upkeep合约,任何人调用upkeep,串联起内部所有的奖励分发逻辑,相关逻辑位于Reward
- 调用liquidizer,执行
performUpkeep- liquidizer把合约内的其他资产都swap成usds,把salt burn掉
- liquidizer会把usdsThatShouldBeBurned尽可能burn掉,如果当前资产不够burn
- 调用dao的
withdrawPOL,从dao获取salt和usds
- 调用dao的
- 调用dao的
withdrawArbitrageProfits,提取套利利润- 把默认5%的利润发给调用者
- 操作合约内的5% weth
- 将各一半的weth去swap出usds和dai
- 把换出来的usds和dai都发送到dao
- 调用dao的formPOL,由dao提供流动性
- 操作合约内的20%weth
- 将各一半的weth去swap出usds和salt
- 把换出来的usds和salt都发送到dao
- 调用dao的
formPOL,由dao提供流动性
- 将合约内的全部weth swap成salt,转移到saltRewards合约
- 计算距离上次调用间隔多久,调用
emissions.performUpkeep- emissions根据间隔线性计算发送多少salt到saltRewards
- 获取当前所有池的套利收入和白名单列表
- 调用saltRewards的
performUpkeep- 先按照比例计算多少salt直接发到salt/usds池子
- 剩余部分按比例,调用
stakingRewardsEmitter.addSALTRewards- 发送到emitter合约
- 记录pool及对应的pending reward
- 剩余部分等分salt,其中saltUSDSPoolID可以多算一笔,调用到
liquidityRewardsEmitter.addSALTRewards
- 调用saltRewards的
- 调用stake和liquidity emitter的performUpkeep方法,传入间隔时间
- 处理pendingreward,线性释放,调用
stakingRewards.addSALTRewards- 把salt转移到stakingRewards合约,累加每个pool的rewards
- 处理pendingreward,线性释放,调用
- 调用dao的
processRewardsFromPOL,由dao来提取分红 - 从dao的vesting钱包转移salt到dao(线性释放)
- 从团队的vesting钱包转移salt到团队钱包(线性释放)