Created
September 28, 2023 02:03
-
-
Save smatthewenglish/da7121f79ac3cc8b0e01f52761a1bd88 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.7.6; | |
pragma abicoder v2; | |
import {Test, console2} from "forge-std/Test.sol"; | |
import {UniswapV3Twap, IUniswapV3Pool} from "../src/UniswapV3Twap.sol"; | |
import {TickMath} from "@uniswap/v3-core/contracts/libraries/TickMath.sol"; | |
import {FullMath} from "@uniswap/v3-core/contracts/libraries/FullMath.sol"; | |
import {FixedPoint96} from "@uniswap/v3-core/contracts/libraries/FixedPoint96.sol"; | |
//forge test --match-path ./test/ForkTest01.t.sol -vv | |
contract ForkTest is Test { | |
IUniswapV3Pool pool; | |
function setUp() public { | |
vm.createSelectFork('https://polygon-mainnet.g.alchemy.com/v2/NlPy1jSLyP-tUCHAuilxrsfaLcFaxSTm', 47983171); | |
pool = IUniswapV3Pool(0x41e64a5Bc929fA8E6a9C8d7E3b81A13b21Ff3045); | |
} | |
function testUniswapV3Twap() public { | |
//uint32 twapInterval = 5 minutes; // with this value 'observe' function on the pool fails with error 'Reason: OLD' | |
uint32 twapInterval = 4 minutes; // TWAP duration in seconds for rebalance check | |
//uint32 twapInterval = 0 minutes; | |
uint256 price = getPrice(address(pool), twapInterval); | |
uint256 precision = 1e15; // 0.001 in Ether (wei notation) | |
uint256 truncatedPrice = (price / precision) * precision; | |
console2.log("truncated price to first three decimal places: %s", truncatedPrice); | |
// This is 5.783 in Ether when considering only the first three decimal places | |
uint256 expectedTruncatedValue = 5783000000000000000; | |
assertEq(truncatedPrice, expectedTruncatedValue); | |
} | |
function getPrice(address poolAddress, uint32 twapInterval) public view returns (uint256 priceInWei) { | |
if (twapInterval == 0) { | |
// return the current price if twapInterval == 0 | |
(uint160 sqrtPriceX96, , , , , , ) = IUniswapV3Pool(poolAddress).slot0(); | |
uint256 priceX96 = FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, FixedPoint96.Q96); | |
priceInWei = _getPriceInWei(priceX96); | |
} else { | |
uint32[] memory secondsAgos = new uint32[](2); | |
secondsAgos[0] = twapInterval; | |
secondsAgos[1] = 0; | |
(int56[] memory tickCumulatives, ) = IUniswapV3Pool(poolAddress).observe(secondsAgos); | |
// tick(imprecise as it's an integer) to price | |
uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(int24((tickCumulatives[1] - tickCumulatives[0]) / twapInterval)); | |
uint256 priceX96 = FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, FixedPoint96.Q96); | |
priceInWei = _getPriceInWei(priceX96); | |
} | |
} | |
function _getPriceInWei(uint256 priceX96) public pure returns (uint256 priceInWei) { | |
priceInWei = (priceX96 * 1e18) / (1 << 96); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment