mai.finance 协议清算套利

分类: 区块链

mai什么

 mai.finance 是一个运作在区块链上去中心化的 0 利率 的借贷协议。用户存入资产,可借出由 mai.finance 发行的稳定币 mai standcoin。借贷期间用户无需支付利息,抵押也不会产生收益。在归还贷款时,协议会收取归还金额的 0.5% 作为协议协议收入。

协议会创建不同的 ERC721 合约用于存放不同类型的资产, 例如:WETH,会创建一个 ERC721 合约,该合约只负责 WETH 的资产的管理。用户存入 WETH ,后续的借贷、还款、清算都由该合约进行控制。用户存入的各种资产额度不共享,风险也是隔离的。

合约分析

mai 协议要求,用户存入的资产与债务的比例在 130(大多数资产的设置,以下都以 130 举例)以上。当某用户资产与债务比例小于 130 时,所有人都可以进场对该用户资产进行清算。清算人可以代为偿还一定债务获取对应价值的资产和一定比例的奖励。

直接看合约:仓库地址 ,主要针对于 erc20Stablecoin.sol 文件。

直接看 liquidateVault 方法

function liquidateVault(uint256 vaultID) external {

        //1. 确认 vaultID 是否存在
        require(_exists(vaultID), "Vault does not exist");
        //2. 检查该合约是否允许对外开放清算
        require(stabilityPool==address(0) || msg.sender ==  stabilityPool, "liquidation is disabled for public");

        //3. 获取该用户的资产与负债情况
        (uint256 collateralValueTimes100, uint256 debtValue) = calculateCollateralProperties(vaultCollateral[vaultID], vaultDebt[vaultID]);

        uint256 collateralPercentage = collateralValueTimes100.div(debtValue);
        // 4. 资产/负载 的比例需要低于 一定系数才允许清算
        require(collateralPercentage < _minimumCollateralPercentage, "Vault is not below minimum collateral percentage");

        // 5. 对于资产价格的获取,协议用的是 chainlink oracle .
        // oracle 部分资产小数位 只有 8 位 amount(18 位) * price(8 位) 得出来的数字 . 多了 8 位小数点
        // 在 calculateCollateralProperties 方法中, 返回的 debtValue 是进行 * 100000000 处理.已便 正确进行资产运算
        // 所以在这里 / 100000000 来还原 debt 价值
        debtValue = debtValue.div(10 ** priceSourceDecimals);

        // 6. 单次最大可代偿金额
        uint256 halfDebt = debtValue.div(debtRatio); //debtRatio (2)

        // 7. 清算发起方余额需要大于债务余额
        require(mai.balanceOf(msg.sender) >= halfDebt, "Token balance too low to pay off outstanding debt");

        //mai
        // 8. 回收债务
        mai.safeTransferFrom(msg.sender, address(this), halfDebt);

        // 9. 获取可获得的资产数量
        uint256 maticExtract = checkExtract(vaultID);
		// 10. 被清算方减去,清算的资产数量
        vaultDebt[vaultID] = vaultDebt[vaultID].sub(halfDebt); // we paid back half of its debt.
		// 11. 协议方收取 0.5% 的费用
        uint256 _closingFee = (halfDebt.mul(closingFee).mul(getTokenPriceSource()) ).div(getEthPriceSource().mul(10000));

        vaultCollateral[vaultID]=vaultCollateral[vaultID].sub(_closingFee);
        vaultCollateral[treasury]=vaultCollateral[treasury].add(_closingFee);

        // deduct the amount from the vault's collateral
        vaultCollateral[vaultID] = vaultCollateral[vaultID].sub(maticExtract);
        // 12. 记录清算获得的资产,而不是直接分发 , 领取奖励需要调用 getPaid() 方法
        // let liquidator take the collateral
        maticDebt[msg.sender] = maticDebt[msg.sender].add(maticExtract);

        emit LiquidateVault(vaultID, ownerOf(vaultID), msg.sender, halfDebt, maticExtract, _closingFee);
    }

根据以上我们能简单分析出来清算的过程

  1. 检查是否可清算
  2. 计算可清算金额及其资产数量
  3. 使用闪电贷得到 mai 进行代还,获得抵押品偿还贷款

清算实现

根据合约实现,可以大致估计出一个清算的大致清算利润。 profio = debtValue / debtRatio * 110 / 100(利润标地 mai )

清算机器人实现

  1. vault 本身就是一个 nft , 所以可以通过遍历所有 tokenId 的方式获取所有用户的账务与资产,并同步到本地
  2. 监听 vault 的事件同步,将用户的资产与账务变动同步到本地
  3. 监听 chainlink oracle 预言机价格变动事件,是实时计算是有有用户的健康阈值低于 130 , 是的话发动清算

协议理解

mai 协议本身即为简单。抵押认可的抵押品借与由自己发行的抵押型稳定币。不需要吸收存款,即可放贷。从而达到 0 利润 ,只需要的支付一定比例的关闭手续费。但是协议成功的关键我认为是,协议发行方需要一个mai:usdt/usdc深度巨大的兑换池用户承载。mai 协议方在 curve.fi 构建了一个 3pool 池子,得以保证 mai 良好流动性。当 mai 跌时,借贷方可以买入 mai 偿还贷款。涨时可以听过抵押借出 mai 进行获利,借用这个机制进行 mai 的价值锚定。


上一篇: 有关程序健壮性的小思考
下一篇: 这是最后一篇了