Skip to content
This repository was archived by the owner on Jun 24, 2025. It is now read-only.

Commit 1538234

Browse files
committed
add another function to estimate one token for another
1 parent 0b5217a commit 1538234

File tree

3 files changed

+36
-9
lines changed

3 files changed

+36
-9
lines changed

src/oracle/IOracle.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ pragma solidity >=0.8.0;
55

66
interface IOracle {
77
function getPrice(address token) external view returns (uint256, uint256);
8+
function getAmountIn(address tokenIn, address tokenOut, uint256 amountOut) external view returns (uint256);
89
}

src/oracle/UniswapV2Oracle.sol

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ contract UniswapV2Oracle is IOracle {
3333
return getTokenValueInUSDT(token, 10 ** IERC20(token).decimals());
3434
}
3535

36+
function getPairAddress(address tokenA, address tokenB) external view returns (address) {
37+
return IUniswapV2Factory(factory).getPair(tokenA, tokenB);
38+
}
39+
3640
function getTokenValueInUSDT(address token, uint256 amount) public view returns (uint256, uint256) {
3741
address pairAddress = IUniswapV2Factory(factory).getPair(token, USDT);
3842
require(pairAddress != address(0), "Pair does not exist");
@@ -51,17 +55,31 @@ contract UniswapV2Oracle is IOracle {
5155
// and pool have 10 eth and 30000 usd then
5256
// 1e18 * 30000USD * 10 ** 1e18 / 10eth * 10 ** 1e6
5357
uint256 price = (amount * reserveUSDT * (10 ** tokenDecimals)) / (reserveToken * (10 ** usdtDecimals));
54-
console.log("price: {}", price);
55-
console.log("reserve0: {}", reserve0);
56-
console.log("reserve1: {}", reserve1);
5758

5859
uint256 scale = 10 ** tokenDecimals;
5960
uint256 integer_part = price / scale;
6061
uint256 fraction = price % scale;
6162
return (integer_part, fraction);
6263
}
6364

64-
function getPairAddress(address tokenA, address tokenB) external view returns (address) {
65-
return IUniswapV2Factory(factory).getPair(tokenA, tokenB);
65+
function getAmountIn(address tokenIn, address tokenOut, uint256 amountOut) external view returns (uint256) {
66+
address pairAddress = IUniswapV2Factory(factory).getPair(tokenIn, tokenOut);
67+
require(pairAddress != address(0), "Pair does not exist");
68+
69+
IUniswapV2Pair pair = IUniswapV2Pair(pairAddress);
70+
71+
(uint112 reserve0, uint112 reserve1,) = pair.getReserves();
72+
require(reserve0 > 0 && reserve1 > 0, "Insufficient liquidity");
73+
74+
bool isToken0In = pair.token0() == tokenIn;
75+
(uint256 reserveIn, uint256 reserveOut) =
76+
isToken0In ? (uint256(reserve0), uint256(reserve1)) : (uint256(reserve1), uint256(reserve0));
77+
78+
uint256 numerator = reserveIn * amountOut * 1000;
79+
// uniswap v2 fee is 0.3%
80+
uint256 denominator = (reserveOut - amountOut) * 997;
81+
uint256 amountIn = (numerator / denominator) + 1;
82+
83+
return amountIn;
6684
}
6785
}

test/UniswapV2Oracle.t.sol

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ pragma solidity >=0.8.0;
66
import {Test, console} from "forge-std/Test.sol";
77
import {UniswapV2Oracle} from "src/oracle/UniswapV2Oracle.sol";
88

9+
interface IERC20 {
10+
function decimals() external view returns (uint8);
11+
}
12+
913
contract UniswapV2OracleTest is Test {
1014
UniswapV2Oracle oracle;
11-
// IUniswapV2Factory factory;
12-
// IUniswapV2Pair pair;
1315

1416
address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
1517
address constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
@@ -21,7 +23,13 @@ contract UniswapV2OracleTest is Test {
2123
}
2224

2325
function testGetNativePrice() public view {
24-
(uint256 ints, uint256 fraction) = oracle.getPrice(WETH);
25-
console.log("WETH/USDT Price:", ints, fraction);
26+
(uint256 ints,) = oracle.getPrice(WETH);
27+
// same query as above one
28+
(uint256 usdtRequired) = oracle.getAmountIn(USDT, WETH, 1 ether);
29+
uint256 usdtDecimals = IERC20(USDT).decimals();
30+
uint256 usdtScale = 10 ** usdtDecimals;
31+
uint256 usdtRequiredForOneEth = usdtRequired / usdtScale;
32+
// adding 20 threshold due to algo of uniswap v2
33+
require(usdtRequiredForOneEth - ints < 20);
2634
}
2735
}

0 commit comments

Comments
 (0)