在翻阅Aave-V2的白皮书的时候,有一章节在讲gas优化的,其中的一些思路值得效仿学习一下
原文链接:https://jusonalien.github.io/post/aave-v2-gas-optimize/
在翻阅Aave-V2的白皮书的时候,有一章节在讲gas优化的,其中的一些思路值得效仿学习一下
在借贷系统中,很多场景涉及到复利率低计算功能,由于这是个幂运算的过程,如果幂数过大会导致计算的迭代次数变多,会增加gas的消耗和性能的降低,在通过对复利公式做二项式展开得到如下公司
$$ (1+x)^α =1+αx+ \frac{1}{2}α(α−1)x^2 + \frac{1}{6}α(α−1)(α−2)x^3 + \frac{1}{24}α(α−1)(α−2)(α−3)x^4 +... $$
会发现,只要保留前三阶项的展开就能满足5年以内的复利率精度
因此我们要计算的的项只有如下
$$ (1+x)^α \approx 1+αx+ \frac{1}{2}α(α−1)x^2 + \frac{1}{6}α(α−1)(α−2)x^3 $$
function calculateCompoundedInterest(
uint256 rate, // 年化利率
uint40 lastUpdateTimestamp, // 利率计算开始时间
uint256 currentTimestamp // 当前时间
) internal pure returns (uint256) {
//solium-disable-next-line
uint256 exp = currentTimestamp.sub(uint256(lastUpdateTimestamp));
if (exp == 0) { // 时间间隔为0,利息不变就是1
return WadRayMath.ray();
}
uint256 expMinusOne = exp - 1;
uint256 expMinusTwo = exp > 2 ? exp - 2 : 0;
uint256 ratePerSecond = rate / SECONDS_PER_YEAR; // 年化利率除一年的秒数
uint256 basePowerTwo = ratePerSecond.rayMul(ratePerSecond);
uint256 basePowerThree = basePowerTwo.rayMul(ratePerSecond);
uint256 secondTerm = exp.mul(expMinusOne).mul(basePowerTwo) / 2;
uint256 thirdTerm = exp.mul(expMinusOne).mul(expMinusTwo).mul(basePowerThree) / 6;
return WadRayMath.ray().add(ratePerSecond.mul(exp)).add(secondTerm).add(thirdTerm);
}
之前的V1版本直接用了OppenZeeplin的SafeMath,导致在做大量的数学运算的时候额外增加了不必要的消耗,V2的版本改成了直接自己在代码库内实现相关的安全数学操作
使用一个256Bit的整数,两两Bit成一对,每一对代表对应的资产,第一个Bit用来表示用户是否用该资产来做抵押物,第二个Bit表示用户是否借用该资产
在V1的版本中是用了List来存放用户的相关信息,相关的操作会比较消耗gas
一些配置只涉及二元逻辑的,实用bitmask来管理,不仅节省gas,在针对多个配置操作的时候还能支持并发的操作
优化都是要经过深度的分析之后才有必要去做,不然都是费时费力不讨好的事情
https://github.com/aave/protocol-v2/blob/master/aave-v2-whitepaper.pdf
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!