Skip to content

Commit

Permalink
Merge pull request #198 from zeriontech/feat/uniswap-v3-forks
Browse files Browse the repository at this point in the history
Uniswap V3 Forks
  • Loading branch information
sobolev-igor authored Sep 18, 2024
2 parents 28dfb65 + e6da111 commit 0aacbb6
Show file tree
Hide file tree
Showing 31 changed files with 1,471 additions and 334 deletions.
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

0 comments on commit 0aacbb6

Please sign in to comment.