-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSentrixV2Library.sol
More file actions
109 lines (99 loc) · 4.8 KB
/
SentrixV2Library.sol
File metadata and controls
109 lines (99 loc) · 4.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {ISentrixV2Pair} from "../interfaces/ISentrixV2Pair.sol";
// Pure helpers — quote, getAmountOut/In, pairFor without on-chain lookup.
//
// `INIT_CODE_HASH` MUST equal `keccak256(type(SentrixV2Pair).creationCode)` of
// the compiled Pair contract that the deployed Factory uses. After Factory is
// deployed (or redeployed), call Factory.pairCodeHash() and patch the constant
// below before deploying Router. If the hash is wrong, pairFor() returns
// addresses that don't match the actual deployed pairs and every Router call
// fails with "INVALID_PAIR" / OOG.
library SentrixV2Library {
// keccak256(type(SentrixV2Pair).creationCode) of the audit-passed Pair
// bytecode (post 2026-04-30 audit hardening — initialize() guard,
// chainid-aware DOMAIN_SEPARATOR). Patched at deploy time. See Deploy.s.sol.
bytes32 internal constant INIT_CODE_HASH = 0xf7d8b4d1ce6c92cb3ce6b366dfb5977578db74e308b88facd5966df9e2a029dd;
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
require(tokenA != tokenB, "SentrixV2Library: IDENTICAL_ADDRESSES");
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), "SentrixV2Library: ZERO_ADDRESS");
}
// Deterministic CREATE2 pair address — no SLOAD, pure computation.
function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {
(address token0, address token1) = sortTokens(tokenA, tokenB);
pair = address(
uint160(
uint256(
keccak256(
abi.encodePacked(hex"ff", factory, keccak256(abi.encodePacked(token0, token1)), INIT_CODE_HASH)
)
)
)
);
}
function getReserves(address factory, address tokenA, address tokenB)
internal
view
returns (uint256 reserveA, uint256 reserveB)
{
(address token0,) = sortTokens(tokenA, tokenB);
(uint256 reserve0, uint256 reserve1,) = ISentrixV2Pair(pairFor(factory, tokenA, tokenB)).getReserves();
(reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
}
function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) internal pure returns (uint256 amountB) {
require(amountA > 0, "SentrixV2Library: INSUFFICIENT_AMOUNT");
require(reserveA > 0 && reserveB > 0, "SentrixV2Library: INSUFFICIENT_LIQUIDITY");
amountB = amountA * reserveB / reserveA;
}
// 0.30% fee (997/1000) — same as UniV2 default.
function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut)
internal
pure
returns (uint256 amountOut)
{
require(amountIn > 0, "SentrixV2Library: INSUFFICIENT_INPUT_AMOUNT");
require(reserveIn > 0 && reserveOut > 0, "SentrixV2Library: INSUFFICIENT_LIQUIDITY");
uint256 amountInWithFee = amountIn * 997;
uint256 numerator = amountInWithFee * reserveOut;
uint256 denominator = reserveIn * 1000 + amountInWithFee;
amountOut = numerator / denominator;
}
function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut)
internal
pure
returns (uint256 amountIn)
{
require(amountOut > 0, "SentrixV2Library: INSUFFICIENT_OUTPUT_AMOUNT");
require(reserveIn > 0 && reserveOut > 0, "SentrixV2Library: INSUFFICIENT_LIQUIDITY");
uint256 numerator = reserveIn * amountOut * 1000;
uint256 denominator = (reserveOut - amountOut) * 997;
amountIn = (numerator / denominator) + 1;
}
function getAmountsOut(address factory, uint256 amountIn, address[] memory path)
internal
view
returns (uint256[] memory amounts)
{
require(path.length >= 2, "SentrixV2Library: INVALID_PATH");
amounts = new uint256[](path.length);
amounts[0] = amountIn;
for (uint256 i; i < path.length - 1; i++) {
(uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i], path[i + 1]);
amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
}
}
function getAmountsIn(address factory, uint256 amountOut, address[] memory path)
internal
view
returns (uint256[] memory amounts)
{
require(path.length >= 2, "SentrixV2Library: INVALID_PATH");
amounts = new uint256[](path.length);
amounts[amounts.length - 1] = amountOut;
for (uint256 i = path.length - 1; i > 0; i--) {
(uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i - 1], path[i]);
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
}
}
}