编译器
0.8.20+commit.a1b79de6
文件 1 的 7:Babylonian.sol
pragma solidity >=0.4.0;
library Babylonian {
function sqrt(uint256 x) internal pure returns (uint256) {
if (x == 0) return 0;
uint256 xx = x;
uint256 r = 1;
if (xx >= 0x100000000000000000000000000000000) {
xx >>= 128;
r <<= 64;
}
if (xx >= 0x10000000000000000) {
xx >>= 64;
r <<= 32;
}
if (xx >= 0x100000000) {
xx >>= 32;
r <<= 16;
}
if (xx >= 0x10000) {
xx >>= 16;
r <<= 8;
}
if (xx >= 0x100) {
xx >>= 8;
r <<= 4;
}
if (xx >= 0x10) {
xx >>= 4;
r <<= 2;
}
if (xx >= 0x8) {
r <<= 1;
}
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
uint256 r1 = x / r;
return (r < r1 ? r : r1);
}
}
文件 2 的 7:BitMath.sol
pragma solidity >=0.5.0;
library BitMath {
function mostSignificantBit(uint256 x) internal pure returns (uint8 r) {
require(x > 0, "BitMath::mostSignificantBit: zero");
if (x >= 0x100000000000000000000000000000000) {
x >>= 128;
r += 128;
}
if (x >= 0x10000000000000000) {
x >>= 64;
r += 64;
}
if (x >= 0x100000000) {
x >>= 32;
r += 32;
}
if (x >= 0x10000) {
x >>= 16;
r += 16;
}
if (x >= 0x100) {
x >>= 8;
r += 8;
}
if (x >= 0x10) {
x >>= 4;
r += 4;
}
if (x >= 0x4) {
x >>= 2;
r += 2;
}
if (x >= 0x2) r += 1;
}
function leastSignificantBit(uint256 x) internal pure returns (uint8 r) {
require(x > 0, "BitMath::leastSignificantBit: zero");
r = 255;
if (x & uint128(340282366920938463463374607431768211455) > 0) {
r -= 128;
} else {
x >>= 128;
}
if (x & uint64(18446744073709551615) > 0) {
r -= 64;
} else {
x >>= 64;
}
if (x & uint32(4294967295) > 0) {
r -= 32;
} else {
x >>= 32;
}
if (x & uint16(32767) > 0) {
r -= 16;
} else {
x >>= 16;
}
if (x & uint8(255) > 0) {
r -= 8;
} else {
x >>= 8;
}
if (x & 0xf > 0) {
r -= 4;
} else {
x >>= 4;
}
if (x & 0x3 > 0) {
r -= 2;
} else {
x >>= 2;
}
if (x & 0x1 > 0) r -= 1;
}
}
文件 3 的 7:FixedPoint.sol
pragma solidity >=0.4.0;
import "./FullMathV2.sol";
import "./Babylonian.sol";
import "./BitMath.sol";
library FixedPoint {
struct uq112x112 {
uint224 _x;
}
struct uq144x112 {
uint256 _x;
}
uint8 public constant RESOLUTION = 112;
uint256 public constant Q112 = 0x10000000000000000000000000000;
uint256 private constant Q224 = 0x100000000000000000000000000000000000000000000000000000000;
uint256 private constant LOWER_MASK = 0xffffffffffffffffffffffffffff;
function encode(uint112 x) internal pure returns (uq112x112 memory) {
return uq112x112(uint224(x) << RESOLUTION);
}
function encode144(uint144 x) internal pure returns (uq144x112 memory) {
return uq144x112(uint256(x) << RESOLUTION);
}
function decode(uq112x112 memory self) internal pure returns (uint112) {
return uint112(self._x >> RESOLUTION);
}
function decode144(uq144x112 memory self) internal pure returns (uint144) {
return uint144(self._x >> RESOLUTION);
}
function mul(uq112x112 memory self, uint256 y) internal pure returns (uq144x112 memory) {
uint256 z = 0;
require(y == 0 || (z = self._x * y) / y == self._x, "FixedPoint::mul: overflow");
return uq144x112(z);
}
function muli(uq112x112 memory self, int256 y) internal pure returns (int256) {
uint256 z = FullMathV2.mulDiv(self._x, uint256(y < 0 ? -y : y), Q112);
require(z < 2 ** 255, "FixedPoint::muli: overflow");
return y < 0 ? -int256(z) : int256(z);
}
function muluq(uq112x112 memory self, uq112x112 memory other) internal pure returns (uq112x112 memory) {
if (self._x == 0 || other._x == 0) {
return uq112x112(0);
}
uint112 upper_self = uint112(self._x >> RESOLUTION);
uint112 lower_self = uint112(self._x & LOWER_MASK);
uint112 upper_other = uint112(other._x >> RESOLUTION);
uint112 lower_other = uint112(other._x & LOWER_MASK);
uint224 upper = uint224(upper_self) * upper_other;
uint224 lower = uint224(lower_self) * lower_other;
uint224 uppers_lowero = uint224(upper_self) * lower_other;
uint224 uppero_lowers = uint224(upper_other) * lower_self;
require(upper <= uint112(5192296858534827628530496329220095), "FixedPoint::muluq: upper overflow");
uint256 sum = uint256(upper << RESOLUTION) + uppers_lowero + uppero_lowers + (lower >> RESOLUTION);
require(
sum <= uint224(26959946667150639794667015087019630673637144422540572481103610249215),
"FixedPoint::muluq: sum overflow"
);
return uq112x112(uint224(sum));
}
function divuq(uq112x112 memory self, uq112x112 memory other) internal pure returns (uq112x112 memory) {
require(other._x > 0, "FixedPoint::divuq: division by zero");
if (self._x == other._x) {
return uq112x112(uint224(Q112));
}
if (self._x <= uint144(22300745198530623141535718272648361505980415)) {
uint256 value = (uint256(self._x) << RESOLUTION) / other._x;
require(
value <= uint224(26959946667150639794667015087019630673637144422540572481103610249215),
"FixedPoint::divuq: overflow"
);
return uq112x112(uint224(value));
}
uint256 result = FullMathV2.mulDiv(Q112, self._x, other._x);
require(
result <= uint224(26959946667150639794667015087019630673637144422540572481103610249215),
"FixedPoint::divuq: overflow"
);
return uq112x112(uint224(result));
}
function fraction(uint256 numerator, uint256 denominator) internal pure returns (uq112x112 memory) {
require(denominator > 0, "FixedPoint::fraction: division by zero");
if (numerator == 0) return FixedPoint.uq112x112(0);
if (numerator <= uint144(22300745198530623141535718272648361505980415)) {
uint256 result = (numerator << RESOLUTION) / denominator;
require(
result <= uint224(26959946667150639794667015087019630673637144422540572481103610249215),
"FixedPoint::fraction: overflow"
);
return uq112x112(uint224(result));
} else {
uint256 result = FullMathV2.mulDiv(numerator, Q112, denominator);
require(
result <= uint224(26959946667150639794667015087019630673637144422540572481103610249215),
"FixedPoint::fraction: overflow"
);
return uq112x112(uint224(result));
}
}
function reciprocal(uq112x112 memory self) internal pure returns (uq112x112 memory) {
require(self._x != 0, "FixedPoint::reciprocal: reciprocal of zero");
require(self._x != 1, "FixedPoint::reciprocal: overflow");
return uq112x112(uint224(Q224 / self._x));
}
function sqrt(uq112x112 memory self) internal pure returns (uq112x112 memory) {
if (self._x <= uint144(22300745198530623141535718272648361505980415)) {
return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << 112)));
}
uint8 safeShiftBits = 255 - BitMath.mostSignificantBit(self._x);
safeShiftBits -= safeShiftBits % 2;
return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << safeShiftBits) << ((112 - safeShiftBits) / 2)));
}
}
文件 4 的 7:FullMathV2.sol
pragma solidity >=0.4.0;
library FullMathV2 {
function fullMul(uint256 x, uint256 y) internal pure returns (uint256 l, uint256 h) {
uint256 mm = mulmod(x, y, type(uint256).max);
l = x * y;
h = mm - l;
if (mm < l) h -= 1;
}
function fullDiv(uint256 l, uint256 h, uint256 d) private pure returns (uint256) {
uint256 pow2 = d & type(uint256).max - d + 1;
d /= pow2;
l /= pow2;
l += h * ((type(uint256).max - pow2 + 1) / pow2 + 1);
uint256 r = 1;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
return l * r;
}
function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256) {
(uint256 l, uint256 h) = fullMul(x, y);
uint256 mm = mulmod(x, y, d);
if (mm > l) h -= 1;
l -= mm;
if (h == 0) return l / d;
require(h < d, "FullMath: FULLDIV_OVERFLOW");
return fullDiv(l, h, d);
}
}
文件 5 的 7:IUniswapV2Factory.sol
pragma solidity >=0.5.0;
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}
文件 6 的 7:SafeMath.sol
pragma solidity >=0.6.12;
library SafeMathUniswap {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x, "ds-math-add-overflow");
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x, "ds-math-sub-underflow");
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
}
}
文件 7 的 7:V2Oracle.sol
pragma solidity >=0.6.6;
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import "./uniswapv2/libraries/FixedPoint.sol";
import "./uniswapv2/libraries/SafeMath.sol";
interface IUniswapV2PairLocal {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint256);
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external;
event Mint(address indexed sender, uint256 amount0, uint256 amount1);
event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
event Swap(
address indexed sender,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint256);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint256);
function price1CumulativeLast() external view returns (uint256);
function kLast() external view returns (uint256);
function mint(address to) external returns (uint256 liquidity);
function burn(address to) external returns (uint256 amount0, uint256 amount1);
function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
library UniswapV2OracleLibrary {
using FixedPoint for *;
function currentBlockTimestamp() internal view returns (uint32) {
return uint32(block.timestamp % 2 ** 32);
}
function currentCumulativePrices(address pair)
internal
view
returns (uint256 price0Cumulative, uint256 price1Cumulative, uint32 blockTimestamp)
{
blockTimestamp = currentBlockTimestamp();
price0Cumulative = IUniswapV2PairLocal(pair).price0CumulativeLast();
price1Cumulative = IUniswapV2PairLocal(pair).price1CumulativeLast();
(uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2PairLocal(pair).getReserves();
if (blockTimestampLast != blockTimestamp) {
uint32 timeElapsed = blockTimestamp - blockTimestampLast;
price0Cumulative += uint256(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed;
price1Cumulative += uint256(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed;
}
}
}
library UniswapV2Library {
using SafeMathUniswap for uint256;
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
require(tokenA != tokenB, "UniswapV2Library: IDENTICAL_ADDRESSES");
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), "UniswapV2Library: ZERO_ADDRESS");
}
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)),
hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f"
)
)
)
)
);
}
function getReserves(address factory, address tokenA, address tokenB)
internal
view
returns (uint256 reserveA, uint256 reserveB)
{
(address token0,) = sortTokens(tokenA, tokenB);
(uint256 reserve0, uint256 reserve1,) =
IUniswapV2PairLocal(IUniswapV2Factory(factory).getPair(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, "UniswapV2Library: INSUFFICIENT_AMOUNT");
require(reserveA > 0 && reserveB > 0, "UniswapV2Library: INSUFFICIENT_LIQUIDITY");
amountB = amountA.mul(reserveB) / reserveA;
}
function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut)
internal
pure
returns (uint256 amountOut)
{
require(amountIn > 0, "UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT");
require(reserveIn > 0 && reserveOut > 0, "UniswapV2Library: INSUFFICIENT_LIQUIDITY");
uint256 amountInWithFee = amountIn.mul(997);
uint256 numerator = amountInWithFee.mul(reserveOut);
uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);
amountOut = numerator / denominator;
}
function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut)
internal
pure
returns (uint256 amountIn)
{
require(amountOut > 0, "UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT");
require(reserveIn > 0 && reserveOut > 0, "UniswapV2Library: INSUFFICIENT_LIQUIDITY");
uint256 numerator = reserveIn.mul(amountOut).mul(1000);
uint256 denominator = reserveOut.sub(amountOut).mul(997);
amountIn = (numerator / denominator).add(1);
}
function getAmountsOut(address factory, uint256 amountIn, address[] memory path)
internal
view
returns (uint256[] memory amounts)
{
require(path.length >= 2, "UniswapV2Library: 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, "UniswapV2Library: 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);
}
}
}
contract V2Oracle {
using FixedPoint for *;
uint256 public constant PERIOD = 5 minutes;
IUniswapV2PairLocal public immutable pair;
address public immutable token0;
address public immutable token1;
uint256 public price0CumulativeLast;
uint256 public price1CumulativeLast;
uint32 public blockTimestampLast;
FixedPoint.uq112x112 public price0Average;
FixedPoint.uq112x112 public price1Average;
constructor(address factory, address tokenA, address tokenB) {
IUniswapV2PairLocal _pair =
IUniswapV2PairLocal(IUniswapV2Factory(factory).getPair(address(tokenA), address(tokenB)));
pair = _pair;
token0 = _pair.token0();
token1 = _pair.token1();
price0CumulativeLast = _pair.price0CumulativeLast();
price1CumulativeLast = _pair.price1CumulativeLast();
uint112 reserve0;
uint112 reserve1;
(reserve0, reserve1, blockTimestampLast) = _pair.getReserves();
require(reserve0 != 0 && reserve1 != 0, "ExampleOracleSimple: NO_RESERVES");
}
function canUpdate() external view returns (bool) {
uint32 blockTimestamp = UniswapV2OracleLibrary.currentBlockTimestamp();
uint32 timeElapsed = blockTimestamp - blockTimestampLast;
return timeElapsed >= PERIOD;
}
function update() external {
(uint256 price0Cumulative, uint256 price1Cumulative, uint32 blockTimestamp) =
UniswapV2OracleLibrary.currentCumulativePrices(address(pair));
uint32 timeElapsed = blockTimestamp - blockTimestampLast;
require(timeElapsed >= PERIOD, "ExampleOracleSimple: PERIOD_NOT_ELAPSED");
price0Average = FixedPoint.uq112x112(uint224((price0Cumulative - price0CumulativeLast) / timeElapsed));
price1Average = FixedPoint.uq112x112(uint224((price1Cumulative - price1CumulativeLast) / timeElapsed));
price0CumulativeLast = price0Cumulative;
price1CumulativeLast = price1Cumulative;
blockTimestampLast = blockTimestamp;
}
function consult(address token, uint256 amountIn) external view returns (uint256 amountOut) {
if (token == token0) {
amountOut = price0Average.mul(amountIn).decode144();
} else {
require(token == token1, "ExampleOracleSimple: INVALID_TOKEN");
amountOut = price1Average.mul(amountIn).decode144();
}
}
}
{
"compilationTarget": {
"src/V2Oracle.sol": "V2Oracle"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
":@uniswap/lib/=lib/solidity-lib/",
":@uniswap/v2-core/=lib/v2-core/",
":@uniswap/v3-core/=lib/v3-core/",
":@uniswap/v3-periphery/=lib/v3-periphery/",
":abdk-libraries-solidity/=lib/abdk-libraries-solidity/",
":base64-sol/=lib/base64/",
":base64/=lib/base64/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":solidity-lib/=lib/solidity-lib/contracts/",
":v2-core/=lib/v2-core/contracts/",
":v3-core/=lib/v3-core/contracts/",
":v3-periphery/=lib/v3-periphery/contracts/"
]
}
[{"inputs":[{"internalType":"address","name":"factory","type":"address"},{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockTimestampLast","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"canUpdate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"consult","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"contract IUniswapV2PairLocal","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price0Average","outputs":[{"internalType":"uint224","name":"_x","type":"uint224"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price0CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price1Average","outputs":[{"internalType":"uint224","name":"_x","type":"uint224"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price1CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"}]