Skip to content

Instantly share code, notes, and snippets.

@smatthewenglish
Created September 28, 2023 02:03
Show Gist options
  • Save smatthewenglish/da7121f79ac3cc8b0e01f52761a1bd88 to your computer and use it in GitHub Desktop.
Save smatthewenglish/da7121f79ac3cc8b0e01f52761a1bd88 to your computer and use it in GitHub Desktop.
// 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