💵
资金池做市
DODO 平台当前的池子类型包括:
- DODO V2 私有池,供专业做市商做市
- DODO V2 公开池,任何用户均可参与,双币做市
- DODO V2 锚定池,任何用户均可参与,双币做市
- DODO V1 经典池,任何用户均可参与,单币做市
DODO V2的私有池 可以由做市商提供自有资金独立做市,并且做市过程中可以灵活修改私有池配置,包括交易手续费率、当前外部指导价格 I、曲线滑点系数 K、同时支持调整池子的资金规模等。这一切修改均由相关账户触发智能合约来实现。
包括两种方式,调用 DODO DPPProxy合约以及直接调用底层私有池,进行做市修改。
第一种方式:
做市商可以通过调用
DODO DPPProxy
(地址见合约信息页)中的resetDODOPrivatePool
方法,以实现动态的做市调整,具体的方法定义如下:function resetDODOPrivatePool(
address dppAddress,
uint256[] memory paramList, //0 - newLpFeeRate, 1 - newI, 2 - newK
uint256[] memory amountList, //0 - baseInAmount, 1 - quoteInAmount, 2 - baseOutAmount, 3- quoteOutAmount
uint8 flag, // 0 - ERC20, 1 - baseInETH, 2 - quoteInETH, 3 - baseOutETH, 4 - quoteOutETH
uint256 minBaseReserve,
uint256 minQuoteReserve,
uint256 deadLine
) external;
- dppAddress: 私有池合约地址
- paramList: 按序传入 交易手续费率、外部指导价格、曲线滑点系数,其中:
- 交易手续费率:单位是 18,范围是[0, 1e18],其中1e18代表100%
- 外部指导价格:单位是 18 - baseToken单位 + quoteToken单位, 外部指导价格是 base/quote 两种代币价格的比例
- 曲线滑点系统:单位是 18,范围是(0, 1e18], 代表价格曲线波动的程度,其中0相当于恒定价格卖币,1e18是类Uni的价格曲线
- amountList:按序传入 baseInAmount、quoteInAmount、baseOutAmount、quoteOutAmount(均考虑各自单位),前两者代表向私有池注入的base与quote的代币数量,注入前,需要将代币授权给
DODOApprove
合约(地址见合约信息页),后两者代表从私有池中提取的base与quote代币数量。从而实现动态调整私有池的资金规模 - flag:主要用于 ETH与WETH 的互转,其中
- 0 代表base与quote均是ERC20代币
- 1 代表转入的base是ETH,因此合约会自动将ETH转为WETH
- 2 代表转入的quote是ETH,因此合约会自动将ETH转为WETH
- 3 代表提取的base是WETH,因此合约会自动将WETH转为ETH
- 4 代表提取的quote是WETH,因此合约会自动将WETH转为ETH
- minBaseReserve与minQuoteReserve 主要用于降低抢跑交易的套利,当做市账户发起交易,修改私有池参数时,有可能会造成池子的价格改变,因此在发出以及真正交易上链的时间间隔内,机器人可能会抢跑套利,这两个参数设定后,当上链执行时池子的现存资金规模有一方小于设定的值,则该笔交易会被合约revert掉,以降低套利风险
- deadline:交易时效,超时后合约revert
DODO DPPProxy ABI:
[
{
"inputs": [
{
"internalType": "address",
"name": "dppAddress",
"type": "address"
},
{
"internalType": "uint256[]",
"name": "paramList",
"type": "uint256[]"
},
{
"internalType": "uint256[]",
"name": "amountList",
"type": "uint256[]"
},
{
"internalType": "uint8",
"name": "flag",
"type": "uint8"
},
{
"internalType": "uint256",
"name": "minBaseReserve",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "minQuoteReserve",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "deadLine",
"type": "uint256"
}
],
"name": "resetDODOPrivatePool",
"outputs": [],
"stateMutability": "payable",
"type": "function"
}
]
第二种方式:
做市商也可以通过直接调用私有池合约,进行做市参数的调整。DODO私有池创建完成后,会包括两个合约
- DPPAdmin (合约的owner为私有池的创建者)
- DPP (底层私有池,存放代币,实现了PMM算法,合约的owner是对应的DPPAdmin合约)
DPPAdmin合约提供了修改做市参数的函数,做市商使用创建私有池的账户有权直接调用。具体的函数包括 :
function reset(
address operator,
uint256 newLpFeeRate,
uint256 newI,
uint256 newK,
uint256 baseOutAmount,
uint256 quoteOutAmount,
uint256 minBaseReserve,
uint256 minQuoteReserve
) external returns (bool)
入参说明:
- operator: DPPAdmin合约owner地址
- newLpFeeRate:新的私有池手续费, 单位是 18,范围是[0, 1e18],其中1e18代表100%
- newI: 新的私有池指导价格,单位是 18 - baseToken单位 + quoteToken单位, 指导价格是 base/quote 两种代币价格的比例
- newK: 新的价格曲线滑点系数,单位是 18,范围是(0, 1e18], 代表价格曲线波动的程度,其中0相当于恒定价格卖币,1e18是类Uni的价格曲线
- baseOutAmount:提取baseToken的数量
- quoteOutAmount:提取quoteToken的数量
- minBaseReserve与minQuoteReserve 主要用于降低抢跑交易的套利,当做市账户发起交易,修改私有池参数时,有可能会造成池子的价格改变,因此在发出以及真正交易上链的时间间隔内,机器人可能会抢跑套利,这两个参数设定后,当上链执行时池子的现存资金规模有一方小于设定的值,则该笔交易会被合约revert掉,以降低套利风险
注:若向私有池补充做市资金,建议直接采用第一种方式,通过DPP Proxy的 resetDODOPrivatePool实现。
如果做市商仅希望改变池子的价格,那么可以直接调用tunePrice函数,这样会节省gas成本。
function tunePrice(
address operator,
uint256 newI,
uint256 minBaseReserve,
uint256 minQuoteReserve
) external returns (bool)
如果做市商仅希望修改池子的做市参数,不涉及做市资金的进出,可以调用 tuneParameters 函数,以节省gas成本。
function tuneParameters(
address operator,
uint256 newLpFeeRate,
uint256 newI,
uint256 newK,
uint256 minBaseReserve,
uint256 minQuoteReserve
java) external returns (bool)
DPPAdmin ABI:
[
{
"inputs": [
{
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"internalType": "uint256",
"name": "newLpFeeRate",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "newI",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "newK",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "minBaseReserve",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "minQuoteReserve",
"type": "uint256"
}
],
"name": "tuneParameters",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"internalType": "uint256",
"name": "newI",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "minBaseReserve",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "minQuoteReserve",
"type": "uint256"
}
],
"name": "tunePrice",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"internalType": "uint256",
"name": "newLpFeeRate",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "newI",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "newK",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "baseOutAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "quoteOutAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "minBaseReserve",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "minQuoteReserve",
"type": "uint256"
}
],
"name": "reset",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
]
该功能主要为DODO平台的做市商提供额外的保护机制,类似于心跳监测,做市商可以在有效时间间隔内,不断更新合约最新的时间戳,以确保私有池参数的时效性。若超过有效时间间隔,那么说明私有池的做市参数过期,为了防止被套利,私有池将会被暂停交易。
该功能适用的典型场景包括区块链网络暂停出块,会导致做市商无法修改最新的做市参数,当暂停出块时间超过设置的有效时间间隔后,私有池将会暂停交易,防止当正常出块后,因为做市参数设置的不准确而被套利抢跑。
若做市商希望启动该功能,可以与DODO平台取得联系(可发送邮件至 [email protected]),提供上链操作的账户地址,以及对应的私有池合约列表,由DODO平台设置后,做市商可以使用提供的账户地址,首先设置有效时间间隔(秒为单位)。最后编写脚本,定时触发 triggerBeat函数,以不断更新最新的时间戳,维护私有池合约的心跳监测时效性。
function setBeatInterval(uint256 interval) external
function triggerBeat() external
- BSC: 0xb5cbFa41C00005562560d6e7A9e3d6A028ed46e5
- Polygon:0xb3a104A96DB375B2c726041c3E954d127538f969
公开池 或者 锚定池 是任何人均可参与的双币做市池,并且由于DODO的灵活设计,相同的交易对可以有不同参数设定的池子,用户参与做市时,按池子当前的比例充入
base
与 quote
资产,获得池子铸造的shares
资产额。注意:shares 代表做市商在资产池中所占份额。其是一个ERC 20 格式的代币,可以自由交易。每个公开池对应一种shares。
function buyShares(
address to
) external returns (uint256 shares, uint256 baseInput, uint256 quoteInput)
这个函数可实现向池子注入流动性,需要做市商构造一笔包含两个操作的交易,第一个操作是按池子当前的base、quote比例,存代币至池子合约,第二个操作是将shares接收地址作为参数,触发buyShares。结束前建议做市商对
baseInput
,quoteInput
这两个实际存入的 代币数量进行数量检查,以确保交易的安全执行 function sellShares(
uint256 shareAmount,
address to,
uint256 baseMinAmount,
uint256 quoteMinAmount,
bytes calldata data,
uint256 deadline
) external returns (uint256 baseAmount, uint256 quoteAmount)
这个函数可实现从池子提取流动性,做市商可以直接调用池子对应的函数执行交易,其中传入的参数包括移除的shares数量、资金接收地址、以及用于滑点保护的baseMinAmount(预期最小接收的base数量),quoteMinAmount(预期最小接收的quote数量),data一般设置为空即可,若不为空,会在函数执行的最后,执行外部合约调用,以实现诸如WETH转为ETH等额外功能,最后的deadline为交易发出后的有效时间,超时自动失败,以保护交易的安全执行
DODOV1 采用 外部预言机价格指导做市,因此支持单币提供流动性,涉及到函数如下:
function depositBaseTo(address to, uint256 amount) external returns (uint256);
function depositQuoteTo(address to, uint256 amount) external returns (uint256);
这两个函数可实现向池子注入单侧流动性,需要做市商构造一笔包含两个操作的交易,第一个操作是将注入的代币授权给池子,第二个操作是触发depositBaseTo 或 depositQuoteTo
function withdrawBase(uint256 amount) external returns (uint256);
function withdrawQuote(uint256 amount) external returns (uint256);
这两个函数可实现从池子中提取单侧流动性,
注:当系统严重偏离平衡状态并且充值或提取的数量很大时,PMM会发放充值奖励或收取提取手续费。一般情况,做市者不用关注这两部分。当然,我们也非常欢迎交易者在系统偏离平衡状态时充值赚取奖励,等系统平衡后提取避免被收取手续费。
最近更新 1yr ago