http://www.7klian.com

Uniswap V2 Oracle和链上累计价值存储证明的团结利用

uniswapMarket.ethToTokenSwapInput.value(100 ether)(100 ether);
  uint public price0CumulativeLast;
  function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
由于在举办这种累加时数学运算的方法,price0CumulativeLast不是price1CumulativeLast的倒数。对付本文档的其余部门,我们将仅引用price0CumulativeLast,但同样合用于这两个值。别的,price0CumulativeLast不必然在每个区块上都是最新的,因此您要么需要在市场上运行sync(),要么本身调解值。
(price0CumulativeLATEST — price0CumulativeFIRST) / 
· 假如不按期挪用,则必需提前打算事务,首先存储当前值,期待一段时间,然后启动利用该汗青值的事务。
address(uniswapMarket).balance
需要会见此Uniswap price的您本身的函数将需要吸收此证明数据作为参数通报给此内部getPrice函数挪用。请参阅Uniswap Oracle自述文件.me集成文档。
price1CumulativeLast是“以token0计价的token1的
价值”
利用以太坊节点的JSON-RPC接口,您可以挪用eth_getProof来检索有效负载,当与该stateRoot值
团结利用时,可以证明存储插槽B上的地点A的值为C。
    if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
由于今朝Uniswap V1市场的“
价值”只是代币和以太余额的比率,因此计较这些项目标gas效率很是高并且很是简朴。可是问题在于它很是不安详。有很多进攻与利用Uniswap V1作为Oracle的项目有关,但最引人注目标进攻大概是bZx/Fulcrum/Compound进攻,它在24小时内净赚近100万美元。
    IUniswapV2Pair uniswapV2Pair,
  return _proposedBlockHash == _realBlockHash;
操作V2作为链上的Oracle,需要“证明”以下各项的先验值:price0CumulativeLast及其对应的块时间戳。
}
· 累积价值Oracle
      price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
在上面的进攻中,您将向活动性提供者付出很是少量的以太币(约0.6 ETH)的用度(双向为0.3%)。可是当挪用exploitTarget时,它会认为令牌比实际值钱得多。假如exploitTarget利用Uniswap V1 oracle来确保您存入的抵押品代价足以提取其他代币,那么该系统将答允您提取比存款凭单多得多的借出代币。
    uint256 blockNumber
    uint8 minBlocksBack,
  // Contract Storage Variables:
// send 100 ether and receive some number of tokens
· 内置多跳路由(ETH->DAI->MKR->USDT,假如这是ETH->USDT的价值)
(timestampOfLATEST — timestampOfFIRST)
    ProofData memory proofData)
  )
2. 利用stateRoot(上面已验证)理会提供的证明(来自JSON-RPC getProof挪用)从该块检索汗青存储值
通过将两个样本中价值
累计的差值除以这两个样本之间的秒数,进程被逆转,功效就是该时段的时间加权价值。您选择的窗口是一个重要的安详思量因素:
Uniswap-Oracle库未经审核。任何对主网有代价的应用措施都应该举办全面审计;请确保您的应用措施的审计也包罗Uniswap的Oracle代码。

function getPrice(
Uniswap V2如何像Oracle一样事情
以太坊合约状态存储在“ Merkle Trie”中,这是一种非凡的数据布局,它答允一个32字节的哈希值代表每个以太坊合约中的每个存储值(具有单独的收据和生意业务数据实验)。这个32字节的值称为stateRoot,是每个以太坊块(以及您大概更熟悉的块,譬喻块号,块哈希和时间戳)的属性。
    uint256 price,
// NOTE: Non-functional pseudo code

为了说明Uniswap V2通过这一新的Oracle成果办理的问题,让我们首先探讨Uniswap V1的问题。

exploitTarget.doSomethingThatUsesUniswapV1AsOracle();
假如您已经相识本文主要的想法,你可以在这里找到代码示例和solidity库:https://github.com/Keydonix/uniswap-oracle。
  uint public price1CumulativeLast;
此时,您可以在纯粹可按照市场动态从完全去中心化的系统中,在一段可设置的时间内平均得到价值。为了让这个价值反馈被哄骗,,进攻者不只需要向一个偏向敦促这个价值,他们还需要在区块之间长时间保持价值稳定,让任何买家都有时机购置价值偏低的资产,这反过来又会更正价值上涨。
· ERC777兼容性
你老是在某种水平上鼓励呆板人不绝更新存储值(呆板人用度来自系统中其他处所的利润),可能要求用户发送两个事务,一个用来获取
累计值,将他们但愿执行的事务延迟一些很是重要的时间,以到达价值馈送平均值所需的秒数。
先容Uniswap Oracle库
  bytes32 _realBlockHash = blockhash(blockNumber);
price0CumulativeLast是“以token1计价的token0的价值”

1. 像上面这样的函数可以验证完整块的具体信息,并确认该块的所有字段都是正确的
  public view
}
要与您本身的智能合约集成,只需简朴地从根基合约UniswapOracle.sol(contract HelloWorld is UniswapOracle)担任,您的合约将担任getPrice函数:
操作存储证明检索汗青累计值
· 两个样本之间的秒数越长,更新的时间越少,但操纵起来就越坚苦。
检索每个值的当前值都很简朴(block.timstamp和uniswapMarket.price0CumulativeLast()),可是如何检索旧值呢?最直接的要领是陈设一个智能合约,该合约将price0CumulativeLast和时间戳的当前值记录到其本身的存储中,以供今后挪用以作为汗青值。尽量这可行,但它有一些缺点:
  }
price(0 | 1)CumulativeLast是独立的存储变量,它们累积“ price-time”。UQ112x112使代码有点难以阅读,但在观念上并不重要;它只充当高精度除法的包装器。这些累积弹性值的“0”和“1”版本之间的独一区别是价值的偏向。
假如你对为呆板人设计经济系统不感乐趣,而且你猜疑用户是否愿意期待发送两个生意业务,有一个更好的要领来操作Uniswap V2作为价值来历:Merkle Patricia Proof!
· 两个样本之间的秒数越少,更新的时间就越多,但更易于操纵。
固然我们凡是认为oracle是一个通过来自受信任/绑定方的生意业务(譬喻Maker Price Feed,ChainLink)将链下信息馈入的系统,但Uniswap V2 oracle不需要任何特定的交互即可提供此数据。取而代之的是,每个互换事务都向该oracle提供信息。

      price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
留意:链上BLOCKHASH查找仅合用于已往256个区块,可用于存储证明的最旧块必需在事务落入链上时位于最后256个区块之内。
  returns (
    address denominationToken,
uniswapMarket.tokenToEthSwapInput(token.balanceOf(address(this));
在上面的例子中,Uniswap V1价值读取是有问题的,因为它们是即时的。V2陈设了一个智慧的系统,用于将价值时间数据记录在链上,这种方法在短时间内操纵本钱很高,而且不行能在单个生意业务中举办操纵。通过利用“累计”价值时间值,可以将价值的可用时间加权为一个非凡值,每次代币掉期城市耗费少量的天然气来保持这些值的同步。
留意:与V1差异,V2是两个代币之间的市场。在内部,这些令牌中的一个需要暗示为token0,另一个暗示为token1。他们的余额由相应的reserve0和reserve1跟踪。Uniswap Docs具有有关令牌排序的更多信息。
  // The only place these storage variables are updated:
Uniswap V1的问题在于价值反馈是即时的,而且很容易在很短的时间内举办操纵。让我们看看下面的psuedo代码示例:
以上计策由少量客户端代码(用于处理惩罚证明)和大量相当巨大的Solidity构成,包罗YUL/assembly和Merkle Trie验证。作为Keydonix开拓团队的一员,Micah Zoltu和我开拓并宣布了Uniswap-Oracle,这是一个Solidity库,使其他智能合约可以操作此oracle成果。
利用链上逻辑,可以将stateRoot和存储证明
团结起来以验证存储插槽的值。假如我们针对Uniswap V2市场和price0CumulativeLast的存储插槽,则可以实现所需的基于证明的汗青查找。
Uniswap团队从未将Uniswap V1推广为可行的链上Oracle。正是由于Uniswap简朴、无许可、链上、面向市场的成果,才吸引了有缔造力的人将其作为一个整体来利用。Uniswap V1 oracle的警报器很简朴:
利用智能合约检索汗青累计值
function verifyBlock(parentBlock, stateRoot, blockNumber, timestamp, …) returns (bool) {
    uint32 timeElapsed = blockTimestamp – blockTimestampLast;
    blockTimestampLast = blockTimestamp;

不要将Uniswap V1用作Oracle
可是stateRoot查找不能作为EVM操纵码利用。独一相关的操纵码是BLOCKHASH,它回收blockNumber并返回32字节的区块哈希。块的blockhash是一个简朴的Keccak256哈希,它具有rlp编码的所有各类属性。通过提供一个区块的所有属性(包罗stateRoot),我们可以通过散列并将其与链上blockHash查找举办较量,从而验证原始块数据是否有效。验证之后,我们便可以利用区块的必须属性(时间戳和stateRoot)。
· 必需按期挪用以存储快照值,假如您但愿该价值馈送在未来一连可用。
在本文中,我们将接头此“累加价值Oracle”其事情方法,如何利用它,并先容一个Solidity库,可以用来将这个Oracle集成到您本身的项目中。本文将假设您对Uniswap等defi产物市场有深入的相识。
  bytes32 _proposedBlockHash = keccek256(rlpEncode(parentBlock, stateRoot, blockNumber, timestamp, …));
在防改动和最新之间找到正确的均衡点应该仔细思量您的项目。

Uniswap V2宣布了很多新成果,包罗:
// send all the tokens we received above back
· 令牌:令牌活动性对(取代ETH/DAI和ETH/MKR,Uniswap V2此刻原生支持MKR/DAI)
3. 从Uniswap market获取当前价值0累积最新值
此刻我们已经有了计较这个价值的公式,但仍然存在一个问题:如何检索链上的汗青价值累积信息?
4. 通过将price0CumulativeLast中的增量除以自验证时间戳以来的秒数,计较所提供块(来自验证的时间戳)和此刻之间的平均价值。
    }
price0CumulativeLast是一个值,它只更新区块上的第一个事务,取最后一个已知的reserve0和reserve1值(token0和token1的令牌余额),计较它们的比率(price),并按price0CumulativeLast上次更新后的秒数举办缩放。price0CumulativeLast是一个每秒钟按两个储量的比率递增的值。要将此值转换回价值,需要两个时间点值price0CumulativeLast,利用以下公式:
contract UniswapV2Pair {

以下是Uniswap市场代码片断:
    uint8 maxBlocksBack,
uint256 tokenPrice = token.balanceOf(uniswapMarket) / 

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

相关文章阅读