文章
问答
讲堂
百科图谱
线下集训
更多
提问
发表文章
专栏
活动
文档
工作
集市
发现
Toggle navigation
文章
问答
讲堂
线下集训
专栏
活动
工作
文档
集市
搜索
登录/注册
uniswapV3有没有办法精确计算出输出数量 跨区间有点搞不明白 是需要存储多个区间的流动性吗
0 条评论
分类:
Web3应用
请先
登录
后评论
默认排序
时间排序
2 个回答
banbu
2023-12-07 14:13
当然可以计算,如果我没理解错你说的区间就是tick,我见过两种方式, 一种是把所有tick的数据拿到本地,tick的数据一般用https://thegraph.com/ 的数据, 在本地实现与v3合约链上一样的计算方式做计算,只要数据一样,结果当然一样,只是v3太复杂,实现需要看很多资料。 另一种是调用getPoolTicks从合约拿数据到本地,然后再像第一种方式一样在本地计算。这种比从graph那数据要快的多,可以每秒刷新几次,上一种在某些大链上刷新一次可能要几分钟,但是这种方式我觉得会在附近几个tick深度不够时计算不准。
请先
登录
后评论
老白
2023-12-23 20:23
我给你一段代码,可以通过下面的代码计算 : ```solidity // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.14; import "./interfaces/IUniswapV3Pool.sol"; import "./lib/Path.sol"; import "./lib/PoolAddress.sol"; import "./lib/TickMath.sol"; contract UniswapV3Quoter { using Path for bytes; struct QuoteSingleParams { address tokenIn; address tokenOut; uint24 fee; uint256 amountIn; uint160 sqrtPriceLimitX96; } address public immutable factory; constructor(address factory_) { factory = factory_; } function quote(bytes memory path, uint256 amountIn) public returns ( uint256 amountOut, uint160[] memory sqrtPriceX96AfterList, int24[] memory tickAfterList ) { sqrtPriceX96AfterList = new uint160[](path.numPools()); tickAfterList = new int24[](path.numPools()); uint256 i = 0; while (true) { (address tokenIn, address tokenOut, uint24 fee) = path .decodeFirstPool(); ( uint256 amountOut_, uint160 sqrtPriceX96After, int24 tickAfter ) = quoteSingle( QuoteSingleParams({ tokenIn: tokenIn, tokenOut: tokenOut, fee: fee, amountIn: amountIn, sqrtPriceLimitX96: 0 }) ); sqrtPriceX96AfterList[i] = sqrtPriceX96After; tickAfterList[i] = tickAfter; amountIn = amountOut_; i++; if (path.hasMultiplePools()) { path = path.skipToken(); } else { amountOut = amountIn; break; } } } function quoteSingle(QuoteSingleParams memory params) public returns ( uint256 amountOut, uint160 sqrtPriceX96After, int24 tickAfter ) { IUniswapV3Pool pool = getPool( params.tokenIn, params.tokenOut, params.fee ); bool zeroForOne = params.tokenIn < params.tokenOut; try pool.swap( address(this), zeroForOne, params.amountIn, params.sqrtPriceLimitX96 == 0 ? ( zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1 ) : params.sqrtPriceLimitX96, abi.encode(address(pool)) ) {} catch (bytes memory reason) { return abi.decode(reason, (uint256, uint160, int24)); } } function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes memory data ) external view { address pool = abi.decode(data, (address)); uint256 amountOut = amount0Delta > 0 ? uint256(-amount1Delta) : uint256(-amount0Delta); (uint160 sqrtPriceX96After, int24 tickAfter, , , ) = IUniswapV3Pool( pool ).slot0(); assembly { let ptr := mload(0x40) mstore(ptr, amountOut) mstore(add(ptr, 0x20), sqrtPriceX96After) mstore(add(ptr, 0x40), tickAfter) revert(ptr, 96) } } function getPool( address token0, address token1, uint24 fee ) internal view returns (IUniswapV3Pool pool) { (token0, token1) = token0 < token1 ? (token0, token1) : (token1, token0); pool = IUniswapV3Pool( PoolAddress.computeAddress(factory, token0, token1, fee) ); } } ```
请先
登录
后评论
您需要登录后才可以回答问题,
登录
关注
2
关注
收藏
1
收藏,
1299
浏览
why
提出于 2023-12-07 08:47
×
发送私信
请将文档链接发给晓娜,我们会尽快安排上架,感谢您的推荐!
发给:
内容:
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因: