当前位置:网站首页>Compound RateModel合约解析
Compound RateModel合约解析
2022-06-11 07:22:00 【33357】
原文发布在 https://github.com/33357/smartcontract-apps这是一个面向中文社区,分析市面上智能合约应用的架构与实现的仓库。欢迎关注开源知识项目!
Compound RateModel合约解析
RateModel合约是用来计算 Compound 上特定代币借贷利率的合约,分析它可以知道借贷利率的计算方法。
演示代码仓库:https://github.com/33357/compound-protocol
WhitePaperInterestRateModel.sol
直线型利率模型
合约初始化
- 公共函数(合约内外部都可以调用)
- constructor
- 代码速览
constructor(uint baseRatePerYear, uint multiplierPerYear) public { baseRatePerBlock = baseRatePerYear.div(blocksPerYear); multiplierPerBlock = multiplierPerYear.div(blocksPerYear); emit NewInterestParams(baseRatePerBlock, multiplierPerBlock); } - 参数分析
函数constructor的入参有 2 个,出参有 0 个,对应的解释如下:constructor( uint baseRatePerYear, // 年基准利率 uint multiplierPerYear // 年利率乘数 ) public { ... } - 实现分析
... { // 块基准利率 = 年基准利率 / 年块数 baseRatePerBlock = baseRatePerYear.div(blocksPerYear); // 块利率乘数 = 年利率乘数 / 年块数 multiplierPerBlock = multiplierPerYear.div(blocksPerYear); // 触发事件 NewInterestParams emit NewInterestParams(baseRatePerBlock, multiplierPerBlock); } - 总结
合约需要按block作为时间单位来计算利率,因此需要将baseRatePerYear和multiplierPerYear转换为baseRatePerBlock和multiplierPerBlock。这里的blocksPerYear为2102400,是按照平均15秒一个block计算的。
- 代码速览
- constructor
资金借出率
- 公共函数(合约内外部都可以调用)
- utilizationRate
- 代码速览
function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) { if (borrows == 0) { return 0; } return borrows.mul(1e18).div(cash.add(borrows).sub(reserves)); } - 参数分析
函数utilizationRate的入参有 3 个,出参有 1 个,对应的解释如下:constructor( uint cash, // 代币余额 uint borrows, // 用户借出代币总数 uint reserves // 储备代币总数 ) public view returns ( uint // 资金借出率 ){ ... } - 实现分析
... { // 如果借出代币总数为 0,资金借出率也为 0 if (borrows == 0) { return 0; } // borrows * 1e18 / (cash + borrows - reserves) return borrows.mul(1e18).div(cash.add(borrows).sub(reserves)); } - 总结
utilizationRate用于计算代币的资金借出率,资金借出率的计算公式为资金借出率 = 借出代币总数 / (代币余额 + 借出代币总数 - 储备代币总数)。由于使用无符号整数计算资金借出率会精度不够,所以需要乘以1e18,扩大精度范围。
- 代码速览
- utilizationRate
资金利率
- 公共函数(合约内外部都可以调用)
- getBorrowRate
- 代码速览
function getBorrowRate(uint cash, uint borrows, uint reserves) public view returns (uint) { uint ur = utilizationRate(cash, borrows, reserves); return ur.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); } - 参数分析
函数getBorrowRate的入参有 3 个,出参有 1 个,对应的解释如下:function getBorrowRate( uint cash, // 代币余额 uint borrows, // 用户借出代币总数 uint reserves // 储备代币总数 ) public view returns ( uint // 块借出利率 ) { ... } - 实现分析
... { // 计算资金借出率 uint ur = utilizationRate(cash, borrows, reserves); // ur * multiplierPerBlock / 1e18 + baseRatePerBlock return ur.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); } - 总结
getBorrowRate用于计算代币的块借出利率,块借出利率的计算公式为块借出利率 = 资金借出率 * 块利率乘数 + 块基准利率。由于资金借出率扩大了精度范围,需要除以1e18得到实际值。
- 代码速览
- getSupplyRate
- 代码速览
function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) public view returns (uint) { uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa); uint borrowRate = getBorrowRate(cash, borrows, reserves); uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18); return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18); } - 参数分析
函数getSupplyRate的入参有 4 个,出参有 1 个,对应的解释如下:getSupplyRate( uint cash, // 代币余额 uint borrows, // 用户借出代币总数 uint reserves, // 储备代币总数 uint reserveFactorMantissa // 储备金率 ) public view returns ( uint // 块质押利率 ) { ... } - 实现分析
... { // 1 - reserveFactorMantissa uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa); // 获取借款利率 borrowRate uint borrowRate = getBorrowRate(cash, borrows, reserves); // borrowRate * (1 - reserveFactorMantissa) uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18); // utilizationRate * borrowRate * (1 - reserveFactorMantissa) return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18); } - 总结
getSupplyRate用于计算代币的块质押利率,块质押利率的计算公式为块质押利率 = 资金借出率 * 借款利率 * (1 - 储备金率) = 借款利率 * 资金借出率 * (1 - 储备金率)。由于资金借出率扩大了精度范围,需要除以1e18得到实际值。
- 代码速览
- getBorrowRate
BaseJumpRateModelV2.sol
拐点型利率模型
合约初始化
- 内部函数(仅合约内可以调用)
- constructor
- 代码速览
constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_, address owner_) internal { owner = owner_; updateJumpRateModelInternal(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_); } - 参数分析
函数constructor的入参有 5 个,出参有 0 个,对应的解释如下:constructor( uint baseRatePerYear, // 年基准利率 uint multiplierPerYear // 年利率乘数 uint jumpMultiplierPerYear, // 拐点年利率乘数 uint kink_, // 拐点资金借出率 address owner_ // 所有者 ) internal { ... } - 实现分析
... { // 记录所有者 owner = owner_; // 更新拐点利率模型参数 updateJumpRateModelInternal(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_); } - 总结
拐点型利率模型比直线型利率模型多了拐点年利率乘数和拐点资金借出率这两个参数。
- 代码速览
- updateJumpRateModelInternal
- 代码速览
function updateJumpRateModelInternal(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) internal { baseRatePerBlock = baseRatePerYear.div(blocksPerYear); multiplierPerBlock = (multiplierPerYear.mul(1e18)).div(blocksPerYear.mul(kink_)); jumpMultiplierPerBlock = jumpMultiplierPerYear.div(blocksPerYear); kink = kink_; emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink); } - 参数分析
函数updateJumpRateModelInternal的入参有 4 个,出参有 0 个,对应的解释如下:function updateJumpRateModelInternal( uint baseRatePerYear, // 年基准利率 uint multiplierPerYear // 年利率乘数 uint jumpMultiplierPerYear, // 拐点年利率乘数 uint kink_, // 拐点资金借出率 ) internal { ... } - 实现分析
... { // 块基准利率 = 年基准利率 / 年块数 baseRatePerBlock = baseRatePerYear.div(blocksPerYear); // 块利率乘数 = 年基准利率 / (年块数 * 拐点资金借出率) multiplierPerBlock = (multiplierPerYear.mul(1e18)).div(blocksPerYear.mul(kink_)); // 拐点块利率乘数 = 拐点年利率乘数 / 年块数 jumpMultiplierPerBlock = jumpMultiplierPerYear.div(blocksPerYear); // 记录拐点资金借出率 kink = kink_; // 触发事件 NewInterestParams emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink); } - 总结
拐点型利率模型中计算块利率乘数时,方法和直线型利率模型不一样:拐点资金借出率越高,块利率乘数越低,其目的我不是很清楚。(可能是拐点资金借出率越高的代币市场深度越好,块利率乘数可以设置的更低,大家可以讨论一下)
- 代码速览
- constructor
资金借出率
- 公共函数(合约内外部都可以调用)
- utilizationRate
- 代码速览
function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) { if (borrows == 0) { return 0; } return borrows.mul(1e18).div(cash.add(borrows).sub(reserves)); } - 参数分析
函数utilizationRate的入参有 3 个,出参有 1 个,对应的解释如下:constructor( uint cash, // 代币余额 uint borrows, // 用户借出代币总数 uint reserves // 储备代币总数 ) public view returns ( uint // 资金借出率 ){ ... } - 实现分析
... { // 如果借出代币总数为 0,资金借出率也为 0 if (borrows == 0) { return 0; } // 资金借出率 = borrows * 1e18 / (cash + borrows - reserves) return borrows.mul(1e18).div(cash.add(borrows).sub(reserves)); } - 总结
拐点型利率模型中计算资金借出率和直线型利率模型相同。
- 代码速览
- utilizationRate
资金利率
- 内部函数(仅合约内部可以调用)
- getBorrowRate
- 代码速览
function getBorrowRateInternal(uint cash, uint borrows, uint reserves) internal view returns (uint) { uint util = utilizationRate(cash, borrows, reserves); if (util <= kink) { return util.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); } else { uint normalRate = kink.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); uint excessUtil = util.sub(kink); return excessUtil.mul(jumpMultiplierPerBlock).div(1e18).add(normalRate); } } - 参数分析
函数getBorrowRateInternal的入参有 3 个,出参有 1 个,对应的解释如下:function getBorrowRate( uint cash, // 代币余额 uint borrows, // 用户借出代币总数 uint reserves // 储备代币总数 ) internal view returns ( uint // 块借出利率 ) { ... } - 实现分析
{ // 获取资金借出率 util uint util = utilizationRate(cash, borrows, reserves); // 如果 util < kink if (util <= kink) { // return util * multiplierPerBlock + baseRatePerBlock return util.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); } else { // 拐点前块借出利率 = kink * multiplierPerBlock + baseRatePerBlock uint normalRate = kink.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock); // 超出拐点资金借出率 = util - kink uint excessUtil = util.sub(kink); // 块借出利率 = (util - kink) * jumpMultiplierPerBlock + kink * multiplierPerBlock + baseRatePerBlock return excessUtil.mul(jumpMultiplierPerBlock).div(1e18).add(normalRate); } } - 总结
拐点型利率模型中计算块借出利率的计算公式分为两部份:在资金借出率低于拐点资金借出率时,计算公式为:块借出利率 = 资金借出率 * 块利率乘数 + 块基准利率;在资金借出率高于拐点资金借出率时,计算公式为:块借出利率 = (资金借出率 - 拐点资金借出率) * 拐点块利率乘数 + 拐点资金借出率 * 块利率乘数 + 块基准利率。
- 代码速览
- getSupplyRate
- 代码速览
function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) public view returns (uint) { uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa); uint borrowRate = getBorrowRateInternal(cash, borrows, reserves); uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18); return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18); } - 参数分析
函数getSupplyRate的入参有 4 个,出参有 1 个,对应的解释如下:getSupplyRate( uint cash, // 代币余额 uint borrows, // 用户借出代币总数 uint reserves, // 储备代币总数 uint reserveFactorMantissa // 储备金率 ) public view returns ( uint // 块质押利率 ) { ... } - 实现分析
... { // 1 - reserveFactorMantissa uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa); // 获取借款利率 borrowRate uint borrowRate = getBorrowRateInternal(cash, borrows, reserves); // rateToPool = borrowRate * (1 - reserveFactorMantissa) uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18); // 块质押利率 = utilizationRate * borrowRate * (1 - reserveFactorMantissa) return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18); } - 总结
拐点型利率模型中计算资金质押利率和直线型利率模型相同。
- 代码速览
- getBorrowRate
边栏推荐
- Leetcode-647. Palindromic Substrings
- Raspberry pie builds a full-featured NAS server (07): manage your library & read as you please
- Promise details
- [并发进阶]——线程池总结
- P5431 [template] multiplicative inverse 2
- Group arrays by a specified size
- Bat (batch processing) processing special symbols (exclamation point, percent sign), etc
- 【CF#388 (Div. 2)】A. Bachgold Problem
- [STL source code analysis] summary notes (12): functors and adapters
- [advanced concurrency] - thread pool summary
猜你喜欢

10 advanced concepts that must be understood in learning SQL

如果要存 IP 地址,用什么数据类型比较好?99%人都会答错!

一、SQLServer2008安裝(帶密碼)、創建數據庫、C#窗體項目測試

Esp32 learning notes (49) - esp-wifi-mesh interface use

Leetcode-141. Linked List Cycle
![[STL source code analysis] summary notes (10): hashtable exploration](/img/31/a77ac380dbd0f85957bd1df1b906f5.jpg)
[STL source code analysis] summary notes (10): hashtable exploration

【编译原理】05-语法制导的语义计算——基于翻译模式的语义计算

Gobang interface of mobile console (C language)

matplotlib的cmap

教育专家王中泽老师:家庭教育重在自己成长
随机推荐
【CF#223 (Div. 2)】A. Sereja and Dima
【CF#697 (Div. 3)】 A - Odd Divisor
Bat (batch processing) processing special symbols (exclamation point, percent sign), etc
2、 User login and registration
webserver
Listen to the left width of the browser to calculate the distance
1269. number of options left in place
Concurrent tool class
Gobang interface of mobile console (C language)
【LeetCode】-- 17. Letter combination of telephone number
Leetcode-647.Palindromic Substrings
資深OpenStacker - 彭博、Vexxhost昇級為OpenInfra基金會黃金成員
[STL source code analysis] summary notes (10): hashtable exploration
Server parameter adjustment record
421. maximum XOR value of two numbers in the array
Promise details
Typora set markdown syntax inline mode
Interview question 17.08 Circus tower
一、SQLServer2008安装(带密码)、创建数据库、C#窗体项目测试
Education expert wangzhongze solves students' problems with one move