Compound简化版v2

  • bixia1994
  • 更新于 2021-11-18 12:09
  • 阅读 3204

在具体写代码的时候,会发现一个问题:即如何合适的表达小数?一种简单的思路是把小数都乘以10^18,但是需要考虑到会不会溢出,以及后续还需要一个除法才行。

Compound简化版v2

小数乘法

在具体写代码的时候,会发现一个问题:即如何合适的表达小数?一种简单的思路是把小数都乘以10^18,但是需要考虑到会不会溢出,以及后续还需要一个除法才行。

这里看一下compound中是如何对待小数乘法的:

compound中将每一个小数按照精度分为两种:EXP和Double。

对于Exp,compound定义了一个结构体:

uint constant expScale = 1e18;
struct Exp{
    uint mantissa;
}

对于Double,compound定义了一个结构体:

uint constant doubldScale = 1e36;
struct Double{
    uint mantissa;
}

在compound里面用的比较多的是Exp精度的数值,这里着重以Exp来分析小数如何加减乘除:

首先是对于EXP这一结构体的分拆:

function truncate(Exp memory exp) pure internal returns (uint) {
    return exp.mantissa.div(expScale);
}

然后是关于Exp的大小比较:

function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {
    return left.mantissa.lt(right.mantissa);
}

然后是Exp的乘法,这里需要考虑Exp乘以Exp,Exp乘以普通数值,返回结果都是Exp类型

//Exp乘以Exp
function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {
    return Exp({mantissa: a.mantissa.mul(b.mantissa).div(expScale)});
}
//Exp乘以数值
function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {
  return Exp({mantissa: a.mantissa.mul(b)});
}

然后是Exp的除法,这里需要考虑Exp除以Exp,Exp除以普通数值,返回结果都是Exp类型

//Exp除以Exp
//除法的时候要先乘在除,防止精度丢失
function div_(Exp memory a, Exp memroy b) pure internal returns (Exp memory) {
    return Exp({mantissa: a.mantissa.mul(expScale).div(b.mantissa)});
}
function div_(Exp memory a, uint b) pure internal returns (Exp memory) {
    return Exp({mantissa: a.mantissa.div(b)});
}

Exp的加法,减法与之类似,不再赘述。

在本次compound的设计中,为保持简单,就使用compound自己提供的计算小数的函数,不再改编。

这里的关键问题是:

全局变量borrowIndex应该存储的是放大1e18次方之后的数据,还是原始数据呢?

这里应该存储放大后的数据

mantissa的含义应该是单精度数据,并不是认为将它放大10^18次方,而只是认为提高他的精度到10^18次方。

对于:cToken相关的totalSupply, totalBorrows, totalReserves其精度已经就是18位了,就不需要再包装一层。而对于borrowIndex其精度需要提升到18位。

点赞 2
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
bixia1994
bixia1994
0x92Fb...C666
learn to code