【发布时间】:2022-12-21 09:15:59
【问题描述】:
我正在分析 Uniswap V2 核心合约,并注意到 comment
// overflow is desired
为什么需要溢出?
因为,从我的角度来看,当下一行发生溢出时
if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
由于错误的timeElapsed,永远不会是真的。
【问题讨论】:
我正在分析 Uniswap V2 核心合约,并注意到 comment
// overflow is desired
为什么需要溢出?
因为,从我的角度来看,当下一行发生溢出时
if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
由于错误的timeElapsed,永远不会是真的。
【问题讨论】:
在:
uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
由于timeElapsed 是无符号的,如果发生溢出,则其值必然为正,因此表达式timeElapsed > 0 的计算结果必然为真。
如果您打算深入研究 Solidity 代码,那么您可能想学习无符号整数和 Twos Complement 的基本概念。
【讨论】:
该合同写在pragma solidity =0.5.16。在这个版本中为了防止溢出下溢错误,它必须有SafeMath库检查这是额外的操作所以它是一个额外的成本(solidity在v8.0.0之后自动检查溢出下溢)
uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
blockTimestampLast 是更新这两个变量的时间
uint public price0CumulativeLast;
uint public price1CumulativeLast;
timeElapsed类型为uint32,表示无符号整数,取值范围为0到4,294,967,295。为了简化,假设我们的范围是 0-32,假设我们有这些变量
blockTimestamp=30
blockTimestampLast=20
因此timeElapsed=10
假设 10 秒过去了,我们没有更新 price0CumulativeLast 和 price1CumulativeLast 所以 blockTimestampLast=20。 10 秒过去了,blockTimestampLast 没有改变我们期望 timeElapsed=20
10 秒后blockTimestamp 将是 30+10=40。因为我们假设我们的范围是 0-32,blockTimestamp 将是 40-32=8。现在计算timeElapsed
timeElapsed = blockTimestamp - blockTimestampLas
= 8-20 =-12
因为我们在 0-32 -12 意味着 20 秒。所以timeElapsed=20。由于时间差没有改变,因此在这种情况下需要溢出。
但想象一下您添加总成本而我们的范围仍然是 0-32 的情况。现在你的总成本是 25,如果你加上 10 美元的成本,就是 35 美元,在我们的范围内是 3 美元。所以这是不可取的。
【讨论】: