azuro代码分析

https://azuro.org

最近的池子 profit 的 dune 查询：https://dune.com/queries/2513483

池子收益看板： https://tools.defieye.io/superset/dashboard/azuro/?standalone=true

合约地址

以 Polygon 代码为例

Oracle 0x94429f3d92ad38c70e44218460a97021548d17ad
LP 0x7043E4e1c4045424858ECBCED80989FeAfC11B36
Core1 0x3B182e9FbF50398A412d17D7969561E3BfcC4fA4 代码 Core
Core2 0xbb13f8981cefd19ddc5338f0f1e11de45e8a11ca 代码 BetExpress 是对 Core1 的组合投注

LP.addReserve

传入 gameId, lockedReserve, finalReserve, leaf

profit = finalReserve-lockedReserve
profit>0 的时候只分发给 leaf 之前的节点
profit<0 的时候所有 LP 提供者都要亏钱

所以如果你想投入资金，建议先看看当前的 locked 资金占总体的比例，这个比例就是你投入后短时间内面临的最大亏损（因为在这段时间内 lockedReserve 可能被消耗就是 LP 全体亏钱，但如果赚钱了不会分给你）

Core1._calcReserve

Copy
max( abs(reinforcement-funds[0]), abs(reinforcement-funds[1]) )

就是 LP 对这个 condition 最大可能的亏损，所有 condition 加在一起就是 LP 的 locked

Core1.resolveCondition

只在 Core1 里有

所有的 condition 都是只有两方的，outcomeIndex 要么 0 要么 1
假设 0 赢了，那么池子可以获得多少资金呢？应该是 1 投入的资金减去需要支付给 0 的 payout

所以这里有：

Copy
lockedReserve = _calcReserve(reinforcement, funds);
profitReserve = lockedReserve + funds[oppositeIndex] - reinforcement;
addReserve(condition.gameId, lockedReserve, profitReserve, condition.leaf)

可以看出在这里池子的利润就是funds[oppositeIndex] - reinforcement; 就是失败用户投入的本金部分减去了盈利用户赚取的部分，因为 funds 默认值从 reinforcement 开始，用户本金增加他所在方的 funds，扣除赔率放大后的对手方 funds

LP.bet

用户下注的交易 https://dashboard.tenderly.co/tx/polygon/0x97935416834c48f2bce822d1cd18ba01fb58e14b5191f8bd80f9f94a45dc6882

这个是 Core1 的

用户将 USDT 给 LP 然后进入到 Core.putBet
根据当前 virtualFunds、用户投入的 amount 数量和配置的 margin 来更新滑点 CoreTools.calcOdds

这个交易里用户对 0 下注 2u，funds 和 virtualFunds 都是 0 这一方增加 2u，对手方 1 减少本金乘以赔率 2*1.219464097168=2.438928u

Core2 的 betData 是SubBet[] memory subBets, uint64 minOdds

LP.withdrawPayout

会先进入 Core.resolvePayout

Core1 就直接返回 NFT 的持有者和 viewPayout 的结果

但 Core2 还会调用 lp.addReserve 从池子里面扣钱