fix: Configurable fee on USV2 executor.

- This fee is not the same depending on the fork. For example, Pancake V2 uses a 0.25% fee, while the USV2 fee is 0.3%. We were wrongly hard-coding this fee to 0.3%.
This commit is contained in:
TAMARA LIPOWSKI
2025-04-18 16:23:03 -04:00
committed by Diana Carvalho
parent 104e1ecd43
commit 4f9785fdac
4 changed files with 38 additions and 23 deletions

View File

@@ -5,25 +5,28 @@ const hre = require("hardhat");
// Comment out the executors you don't want to deploy // Comment out the executors you don't want to deploy
const executors_to_deploy = { const executors_to_deploy = {
"ethereum": [ "ethereum": [
// USV2 - Args: Factory, Pool Init Code Hash // USV2 - Args: Factory, Pool Init Code Hash, Fee BPS
{ {
exchange: "UniswapV2Executor", args: [ exchange: "UniswapV2Executor", args: [
"0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f", "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f",
"0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f",
30
] ]
}, },
// SUSHISWAP - Args: Factory, Pool Init Code Hash // SUSHISWAP - Args: Factory, Pool Init Code Hash, Fee BPS, Fee BPS
{ {
exchange: "UniswapV2Executor", args: [ exchange: "UniswapV2Executor", args: [
"0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac", "0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac",
"0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303" "0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303",
30
] ]
}, },
// PANCAKESWAP V2 - Args: Factory, Pool Init Code Hash // PANCAKESWAP V2 - Args: Factory, Pool Init Code Hash, Fee BPS
{ {
exchange: "UniswapV2Executor", args: [ exchange: "UniswapV2Executor", args: [
"0x1097053Fd2ea711dad45caCcc45EfF7548fCB362", "0x1097053Fd2ea711dad45caCcc45EfF7548fCB362",
"0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d" "0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d",
25
] ]
}, },
// USV3 -Args: Factory, Pool Init Code Hash // USV3 -Args: Factory, Pool Init Code Hash
@@ -57,25 +60,28 @@ const executors_to_deploy = {
} }
], ],
"base": [ "base": [
// Args: Factory, Pool Init Code Hash // Args: Factory, Pool Init Code Hash, Fee BPS
{ {
exchange: "UniswapV2Executor", args: [ exchange: "UniswapV2Executor", args: [
"0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6", "0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6",
"0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f",
30
] ]
}, },
// SUSHISWAP V2 - Args: Factory, Pool Init Code Hash // SUSHISWAP V2 - Args: Factory, Pool Init Code Hash, Fee BPS
{ {
exchange: "UniswapV2Executor", args: [ exchange: "UniswapV2Executor", args: [
"0x71524B4f93c58fcbF659783284E38825f0622859", "0x71524B4f93c58fcbF659783284E38825f0622859",
"0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303" "0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303",
30
] ]
}, },
// PANCAKESWAP V2 - Args: Factory, Pool Init Code Hash // PANCAKESWAP V2 - Args: Factory, Pool Init Code Hash, Fee BPS
{ {
exchange: "UniswapV2Executor", args: [ exchange: "UniswapV2Executor", args: [
"0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E", "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E",
"0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d" "0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d",
25
] ]
}, },
// USV3 - Args: Factory, Pool Init Code Hash // USV3 - Args: Factory, Pool Init Code Hash
@@ -97,11 +103,12 @@ const executors_to_deploy = {
{exchange: "BalancerV2Executor", args: []}, {exchange: "BalancerV2Executor", args: []},
], ],
"unichain": [ "unichain": [
// Args: Factory, Pool Init Code Hash // Args: Factory, Pool Init Code Hash, Fee BPS
{ {
exchange: "UniswapV2Executor", args: [ exchange: "UniswapV2Executor", args: [
"0x1f98400000000000000000000000000000000002", "0x1f98400000000000000000000000000000000002",
"0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f",
30
] ]
}, },
// USV3 - Args: Factory, Pool Init Code Hash // USV3 - Args: Factory, Pool Init Code Hash

View File

@@ -10,6 +10,7 @@ error UniswapV2Executor__InvalidDataLength();
error UniswapV2Executor__InvalidTarget(); error UniswapV2Executor__InvalidTarget();
error UniswapV2Executor__InvalidFactory(); error UniswapV2Executor__InvalidFactory();
error UniswapV2Executor__InvalidInitCode(); error UniswapV2Executor__InvalidInitCode();
error UniswapV2Executor__InvalidFee();
contract UniswapV2Executor is IExecutor, TokenTransfer { contract UniswapV2Executor is IExecutor, TokenTransfer {
using SafeERC20 for IERC20; using SafeERC20 for IERC20;
@@ -17,8 +18,9 @@ contract UniswapV2Executor is IExecutor, TokenTransfer {
address public immutable factory; address public immutable factory;
bytes32 public immutable initCode; bytes32 public immutable initCode;
address private immutable self; address private immutable self;
uint256 public immutable feeBps;
constructor(address _factory, bytes32 _initCode, address _permit2) constructor(address _factory, bytes32 _initCode, address _permit2, uint256 _feeBps)
TokenTransfer(_permit2) TokenTransfer(_permit2)
{ {
if (_factory == address(0)) { if (_factory == address(0)) {
@@ -29,6 +31,10 @@ contract UniswapV2Executor is IExecutor, TokenTransfer {
} }
factory = _factory; factory = _factory;
initCode = _initCode; initCode = _initCode;
if (_feeBps > 10000) {
revert UniswapV2Executor__InvalidFee();
}
feeBps = _feeBps;
self = address(this); self = address(this);
} }
@@ -100,9 +106,9 @@ contract UniswapV2Executor is IExecutor, TokenTransfer {
} }
require(reserveIn > 0 && reserveOut > 0, "L"); require(reserveIn > 0 && reserveOut > 0, "L");
uint256 amountInWithFee = amountIn * 997; uint256 amountInWithFee = amountIn * (10000 - feeBps);
uint256 numerator = amountInWithFee * uint256(reserveOut); uint256 numerator = amountInWithFee * uint256(reserveOut);
uint256 denominator = (uint256(reserveIn) * 1000) + amountInWithFee; uint256 denominator = (uint256(reserveIn) * 10000) + amountInWithFee;
amount = numerator / denominator; amount = numerator / denominator;
} }

View File

@@ -99,7 +99,7 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper {
IPoolManager poolManager = IPoolManager(poolManagerAddress); IPoolManager poolManager = IPoolManager(poolManagerAddress);
usv2Executor = usv2Executor =
new UniswapV2Executor(factoryV2, initCodeV2, PERMIT2_ADDRESS); new UniswapV2Executor(factoryV2, initCodeV2, PERMIT2_ADDRESS, 30);
usv3Executor = usv3Executor =
new UniswapV3Executor(factoryV3, initCodeV3, PERMIT2_ADDRESS); new UniswapV3Executor(factoryV3, initCodeV3, PERMIT2_ADDRESS);
usv4Executor = new UniswapV4Executor(poolManager, PERMIT2_ADDRESS); usv4Executor = new UniswapV4Executor(poolManager, PERMIT2_ADDRESS);

View File

@@ -8,8 +8,8 @@ import {Constants} from "../Constants.sol";
import {Permit2TestHelper} from "../Permit2TestHelper.sol"; import {Permit2TestHelper} from "../Permit2TestHelper.sol";
contract UniswapV2ExecutorExposed is UniswapV2Executor { contract UniswapV2ExecutorExposed is UniswapV2Executor {
constructor(address _factory, bytes32 _initCode, address _permit2) constructor(address _factory, bytes32 _initCode, address _permit2, uint256 _feeBps)
UniswapV2Executor(_factory, _initCode, _permit2) UniswapV2Executor(_factory, _initCode, _permit2, _feeBps)
{} {}
function decodeParams(bytes calldata data) function decodeParams(bytes calldata data)
@@ -63,17 +63,19 @@ contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper {
uint256 forkBlock = 17323404; uint256 forkBlock = 17323404;
vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock);
uniswapV2Exposed = new UniswapV2ExecutorExposed( uniswapV2Exposed = new UniswapV2ExecutorExposed(
USV2_FACTORY_ETHEREUM, USV2_POOL_CODE_INIT_HASH, PERMIT2_ADDRESS USV2_FACTORY_ETHEREUM, USV2_POOL_CODE_INIT_HASH, PERMIT2_ADDRESS, 30
); );
sushiswapV2Exposed = new UniswapV2ExecutorExposed( sushiswapV2Exposed = new UniswapV2ExecutorExposed(
SUSHISWAPV2_FACTORY_ETHEREUM, SUSHISWAPV2_FACTORY_ETHEREUM,
SUSHIV2_POOL_CODE_INIT_HASH, SUSHIV2_POOL_CODE_INIT_HASH,
PERMIT2_ADDRESS PERMIT2_ADDRESS,
30
); );
pancakeswapV2Exposed = new UniswapV2ExecutorExposed( pancakeswapV2Exposed = new UniswapV2ExecutorExposed(
PANCAKESWAPV2_FACTORY_ETHEREUM, PANCAKESWAPV2_FACTORY_ETHEREUM,
PANCAKEV2_POOL_CODE_INIT_HASH, PANCAKEV2_POOL_CODE_INIT_HASH,
PERMIT2_ADDRESS PERMIT2_ADDRESS,
25
); );
permit2 = IAllowanceTransfer(PERMIT2_ADDRESS); permit2 = IAllowanceTransfer(PERMIT2_ADDRESS);
} }