Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uniswap V3 Forks #198

Merged
merged 4 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .prettierrc.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"plugins": ["prettier-plugin-solidity"],
"overrides": [
{
"files": "*.sol",
Expand All @@ -8,7 +9,6 @@
"useTabs": false,
"singleQuote": false,
"bracketSpacing": true,
"explicitTypes": "always",
"trailingComma": "none"
}
},
Expand Down
11 changes: 9 additions & 2 deletions .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"mark-callable-contracts": ["off"],
"reason-string": ["error", { "maxLength": 50 }],
"function-max-lines": ["error", 99],
"max-line-length": ["error", 99],
"max-line-length": ["off"],
"compiler-version": ["error", "0.8.12"],
"private-vars-leading-underscore": ["off"],
"const-name-snakecase": ["off"],
Expand All @@ -16,6 +16,13 @@
}
],
"prettier/prettier": "warn",
"comprehensive-interface": ["off"]
"comprehensive-interface": ["off"],
"foundry-test-functions": ["off"],
"gas-small-strings": ["off"],
"gas-increment-by-one": ["off"],
"func-named-parameters": ["off"],
"gas-custom-errors": ["off"],
"named-parameters-mapping": ["off"],
"gas-indexed-events": ["off"]
}
}
4 changes: 1 addition & 3 deletions contracts/callers/SimpleCaller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ import { Address } from "@openzeppelin/contracts/utils/Address.sol";

import { ICaller } from "../interfaces/ICaller.sol";
import { Base } from "../shared/Base.sol";
import { ActionType } from "../shared/Enums.sol";
import { HighInputBalanceChange, ZeroTarget } from "../shared/Errors.sol";
import { AbsoluteTokenAmount } from "../shared/Structs.sol";
import { ZeroTarget } from "../shared/Errors.sol";
import { TokensHandler } from "../shared/TokensHandler.sol";

/**
Expand Down
5 changes: 3 additions & 2 deletions contracts/callers/UniswapV2Caller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { IUniswapV2Pair } from "../interfaces/IUniswapV2Pair.sol";
import { IWETH9 } from "../interfaces/IWETH9.sol";
import { Base } from "../shared/Base.sol";
import { SwapType } from "../shared/Enums.sol";
import { BadToken, InconsistentPairsAndDirectionsLengths, InputSlippage, LowReserve, ZeroAmountIn, ZeroAmountOut, ZeroLength } from "../shared/Errors.sol";
import { InconsistentPairsAndDirectionsLengths, InputSlippage, LowReserve, ZeroAmountIn, ZeroAmountOut, ZeroLength } from "../shared/Errors.sol";
import { TokensHandler } from "../shared/TokensHandler.sol";
import { Weth } from "../shared/Weth.sol";

Expand Down Expand Up @@ -68,8 +68,9 @@ contract UniswapV2Caller is ICaller, TokensHandler, Weth {

uint256 length = pairs.length;
if (length == uint256(0)) revert ZeroLength();
if (directions.length != length)
if (directions.length != length) {
revert InconsistentPairsAndDirectionsLengths(length, directions.length);
}

uint256[] memory amounts = (swapType == SwapType.FixedInputs)
? getAmountsOut(fixedSideAmount, pairs, directions)
Expand Down
110 changes: 110 additions & 0 deletions contracts/callers/UniswapV3Caller.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity 0.8.12;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IUniswapV3SwapCallback } from "@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol";
import { IUniswapV3Pool } from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";

import { IWETH9 } from "./../interfaces/IWETH9.sol";
import { Base } from "./../shared/Base.sol";
import { TokensHandler } from "./../shared/TokensHandler.sol";
import { Weth } from "./../shared/Weth.sol";

contract UniswapV3Caller is TokensHandler, Weth, IUniswapV3SwapCallback {
address internal constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
uint160 internal constant MIN_SQRT_RATIO = 4295128739;
uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;

/**
* @notice Sets Wrapped Ether address for the current chain
* @param weth Wrapped Ether address
*/
constructor(address weth) Weth(weth) {
// solhint-disable-previous-line no-empty-blocks
}

function callBytes(bytes calldata callerCallData) external {
(
address inputToken,
address outputToken,
address pool,
bool direction,
uint256 fixedSideAmount,
bool isExactInput
) = abi.decode(callerCallData, (address, address, address, bool, uint256, bool));

if (isExactInput) {
exactInputSwap(inputToken, pool, direction, fixedSideAmount);
} else {
exactOutputSwap(inputToken, pool, direction, fixedSideAmount);
}

// Unwrap weth if necessary
if (outputToken == ETH) withdrawEth();

// In case of non-zero input token, transfer the remaining amount back to `msg.sender`
Base.transfer(inputToken, msg.sender, Base.getBalance(inputToken));

// In case of non-zero output token, transfer the total balance to `msg.sender`
Base.transfer(outputToken, msg.sender, Base.getBalance(outputToken));
}

function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external {
address inputToken = abi.decode(data, (address));

if (amount0Delta > 0) {
if (inputToken == ETH) {
depositEth(uint256(amount0Delta));
}
Base.transfer(IUniswapV3Pool(msg.sender).token0(), msg.sender, uint256(amount0Delta));
} else {
if (inputToken == ETH) {
depositEth(uint256(amount1Delta));
}
Base.transfer(IUniswapV3Pool(msg.sender).token1(), msg.sender, uint256(amount1Delta));
}
}

function exactInputSwap(
address inputToken,
address pool,
bool direction,
uint256 amountIn
) internal {
IUniswapV3Pool(pool).swap(
address(this),
direction,
int256(amountIn),
direction ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,
abi.encode(inputToken)
);
}

function exactOutputSwap(
address inputToken,
address pool,
bool direction,
uint256 amountOut
) internal {
IUniswapV3Pool(pool).swap(
address(this),
direction,
-int256(amountOut),
direction ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,
abi.encode(inputToken)
);
}

function depositEth(uint256 amount) internal {
IWETH9(getWeth()).deposit{ value: amount }();
}

function withdrawEth() internal {
uint256 wethBalance = IERC20(getWeth()).balanceOf(address(this));
if (wethBalance > uint256(0)) IWETH9(getWeth()).withdraw(wethBalance);
}
}
2 changes: 0 additions & 2 deletions contracts/interfaces/ICaller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

pragma solidity 0.8.12;

import { AbsoluteTokenAmount } from "../shared/Structs.sol";

import { ITokensHandler } from "./ITokensHandler.sol";

interface ICaller is ITokensHandler {
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IDAIPermit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ interface IDAIPermit is IERC20 {
bytes32 s
) external;

function nonces(address holder) external view returns (uint256);
function nonces(address holder) external view returns (uint256 nonce);
}
2 changes: 1 addition & 1 deletion contracts/interfaces/IEIP2612.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ interface IEIP2612 is IERC20 {
bytes32 s
) external;

function nonces(address holder) external view returns (uint256);
function nonces(address holder) external view returns (uint256 nonce);
}
16 changes: 5 additions & 11 deletions contracts/interfaces/IRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,9 @@

pragma solidity 0.8.12;

import {
AbsoluteTokenAmount,
Input,
SwapDescription,
AccountSignature,
ProtocolFeeSignature,
Fee
} from "../shared/Structs.sol";

import { ITokensHandler } from "./ITokensHandler.sol";
import { AbsoluteTokenAmount, Input, SwapDescription, AccountSignature, ProtocolFeeSignature } from "../shared/Structs.sol";
import { ISignatureVerifier } from "./ISignatureVerifier.sol";
import { ITokensHandler } from "./ITokensHandler.sol";

interface IRouter is ITokensHandler, ISignatureVerifier {
/**
Expand Down Expand Up @@ -89,7 +81,9 @@ interface IRouter is ITokensHandler, ISignatureVerifier {
SwapDescription calldata swapDescription,
AccountSignature calldata accountSignature,
ProtocolFeeSignature calldata protocolFeeSignature
) external payable
)
external
payable
returns (
uint256 inputBalanceChange,
uint256 actualOutputAmount,
Expand Down
3 changes: 0 additions & 3 deletions contracts/interfaces/ISignatureVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@

pragma solidity 0.8.12;

import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

import { AbsoluteTokenAmount, Input, SwapDescription } from "../shared/Structs.sol";

interface ISignatureVerifier {
Expand Down
22 changes: 9 additions & 13 deletions contracts/interfaces/IUniswapV2Pair.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,23 @@ pragma solidity 0.8.12;
* github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2Pair.sol.
*/
interface IUniswapV2Pair {
function mint(address) external returns (uint256);
function mint(address to) external returns (uint256 liquidity);

function burn(address) external returns (uint256, uint256);
function burn(address to) external returns (uint256 amount0, uint256 amount1);

function swap(
uint256,
uint256,
address,
bytes calldata
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;

function getReserves()
external
view
returns (
uint112,
uint112,
uint32
);
returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);

function token0() external view returns (address);
function token0() external view returns (address token0);

function token1() external view returns (address);
function token1() external view returns (address token1);
}
8 changes: 4 additions & 4 deletions contracts/interfaces/IUniswapV2Router02.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ pragma solidity 0.8.12;
*/
interface IUniswapV2Router02 {
function swapExactETHForTokens(
uint256,
address[] calldata,
address,
uint256
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
}
4 changes: 2 additions & 2 deletions contracts/interfaces/IWETH9.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pragma solidity 0.8.12;
interface IWETH9 {
function deposit() external payable;

function withdraw(uint256) external;
function withdraw(uint256 amount) external;

function balanceOf(address) external view returns (uint256);
function balanceOf(address account) external view returns (uint256 balance);
}
8 changes: 1 addition & 7 deletions contracts/interfaces/IYearnPermit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,5 @@ pragma solidity 0.8.12;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IYearnPermit is IERC20 {
function permit(
address,
address,
uint256,
uint256,
bytes calldata
) external;
function permit(address, address, uint256, uint256, bytes calldata) external;
}
Loading
Loading