Skip to content
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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@
[submodule "lib/v3-core"]
path = lib/v3-core
url = https://github.com/uniswap/v3-core
[submodule "lib/chainlink-brownie-contracts"]
path = lib/chainlink-brownie-contracts
url = https://github.com/smartcontractkit/chainlink-brownie-contracts
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"solidity.compileUsingRemoteVersion": "v0.8.18+commit.87f61d96"
}
6 changes: 6 additions & 0 deletions foundry.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
"lib/balancer-v2-monorepo": {
"rev": "36d282374b457dddea828be7884ee0d185db06ba"
},
"lib/chainlink-brownie-contracts": {
"tag": {
"name": "1.3.0",
"rev": "5cb41fbc9b525338b6098da5ea7dd0b7e92f89e4"
}
},
"lib/forge-std": {
"rev": "b93cf4bc34ff214c099dc970b153f85ade8c9f66"
},
Expand Down
14 changes: 9 additions & 5 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
src = "src"
out = "out"
libs = ["lib"]
solc_version = "0.8.18"
via_ir = false

remappings = [
"forge-std/=lib/forge-std/src/",
"@balancer/balancer-v2-monorepo/pkg/=lib/balancer-v2-monorepo/pkg/",
"@openzeppelin/openzeppelin-contracts/contracts/=lib/openzeppelin-contracts/contracts/",
"@uniswap/v3-periphery/contracts/interfaces=lib/v3-periphery/contracts/interfaces",
"@balancer-labs/v2-interfaces/=lib/balancer-v2-monorepo/pkg/interfaces/",
"@balancer-labs/v2-vault/=lib/balancer-v2-monorepo/pkg/vault/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@uniswap/v3-periphery/contracts/interfaces/=lib/v3-periphery/contracts/interfaces/",
"@uniswap/v3-core/contracts/interfaces/=lib/v3-core/contracts/interfaces/",
]
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
"@chainlink/contracts/=lib/chainlink-brownie-contracts/contracts/",
]
1 change: 1 addition & 0 deletions lib/chainlink-brownie-contracts
10 changes: 5 additions & 5 deletions script/DeployArbitrage.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.13;

import {Script, console2} from "forge-std/Script.sol";
import {FlashArbitrage} from "../src/FlashArbitrage.sol";
import {Arbitrage} from "../src/FlashArbitrage.sol";
import {HelperConfig} from "../script/HelperConfig.s.sol";

/**
Expand Down Expand Up @@ -32,7 +32,7 @@ contract DeployArbitrage is Script {

/// @notice The deployed FlashArbitrage contract instance
/// @dev Main arbitrage contract that will be deployed and configured
FlashArbitrage public flashArbitrage;
Arbitrage public flashArbitrage;

//////////////////////////////////////////////////////////////
// FUNCTIONS //
Expand All @@ -46,7 +46,7 @@ contract DeployArbitrage is Script {
*/
function setUp() public {
helperConfig = new HelperConfig();
modeConfig = helperConfig.getSepoliaETHConfig();
SepoliaConfig = helperConfig.getSepoliaETHConfig();
}

/**
Expand All @@ -58,12 +58,12 @@ contract DeployArbitrage is Script {
* @custom:gas Consider gas optimization and limit settings for mainnet deployment
* @custom:network Verify network configuration before deployment to avoid wrong network deployment
*/
function run() public returns (FlashArbitrage) {
function run() public returns (Arbitrage) {
// Start broadcasting transactions - required for actual deployment
vm.startBroadcast();

// Deploy the FlashArbitrage contract with default constructor parameters
flashArbitrage = new FlashArbitrage();
flashArbitrage = new Arbitrage();

// Stop broadcasting transactions
vm.stopBroadcast();
Expand Down
2 changes: 1 addition & 1 deletion script/PriceManipulation.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity 0.8.18;

import {Script, console} from "forge-std/Script.sol";
import {HelperConfig} from "./HelperConfig.s.sol";
import {IERC20} from "@openzeppelin/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import {IQuoterV2} from "@uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol";

Expand Down
6 changes: 3 additions & 3 deletions script/Swap.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
pragma solidity ^0.8.13;

import {Script, console} from "forge-std/Script.sol";
import {FlashArbitrage} from "../src/FlashArbitrage.sol";
import {Arbitrage} from "../src/FlashArbitrage.sol";
import {DeployArbitrage} from "../script/DeployArbitrage.s.sol";
import {HelperConfig} from "../script/HelperConfig.s.sol";
import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import {IQuoterV2} from "@uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol";
import {IERC20} from "@openzeppelin/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract Swap is Script {
FlashArbitrage public arbitrage;
Arbitrage public arbitrage;
HelperConfig public helperConfig;
HelperConfig.NetworkConfig currentConfig;

Expand Down
20 changes: 11 additions & 9 deletions src/FlashArbitrageV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import {IQuoterV2} from "@uniswap/v3-periphery/contracts/interfaces/IQuoterV2.so
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

/**
* @title ImprovedFlashArbitrage
Expand All @@ -32,8 +30,6 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
* @custom:optimization Gas-optimized storage layout and execution paths
*/
contract ImprovedFlashArbitrage is IFlashLoanRecipient, ReentrancyGuard, Ownable, Pausable {
using SafeERC20 for IERC20;

//////////////////////////////////////////////////////////////
// CONSTANTS //
//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -148,6 +144,12 @@ contract ImprovedFlashArbitrage is IFlashLoanRecipient, ReentrancyGuard, Ownable
/// @param unlockTime Timestamp when withdrawal becomes available
event EmergencyWithdrawalInitiated(uint256 unlockTime);

/// @notice Emitted when emergency withdrawal is executed
/// @param token Token address withdrawn
/// @param amount Amount withdrawn
/// @param recipient Recipient address
event EmergencyWithdrawal(address indexed token, uint256 amount, address indexed recipient);

//////////////////////////////////////////////////////////////
// MODIFIERS //
//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -267,12 +269,12 @@ contract ImprovedFlashArbitrage is IFlashLoanRecipient, ReentrancyGuard, Ownable
require(finalBalance >= initialBalance + expectedMinOut, "Insufficient profit realized");

// Repay flash loan
tokens[0].safeTransfer(address(VAULT), flashAmount);
tokens[0].transfer(address(VAULT), flashAmount);

// Calculate and transfer profit
uint256 profit = finalBalance - initialBalance - flashAmount;
if (profit > 0) {
tokens[0].safeTransfer(profitRecipient, profit);
tokens[0].transfer(profitRecipient, profit);
}

// Emit success event
Expand Down Expand Up @@ -336,7 +338,7 @@ contract ImprovedFlashArbitrage is IFlashLoanRecipient, ReentrancyGuard, Ownable

require(withdrawAmount <= balance, "Insufficient balance");

tokenContract.safeTransfer(profitRecipient, withdrawAmount);
tokenContract.transfer(profitRecipient, withdrawAmount);
emit EmergencyWithdrawal(token, withdrawAmount, profitRecipient);
}

Expand Down Expand Up @@ -401,7 +403,7 @@ contract ImprovedFlashArbitrage is IFlashLoanRecipient, ReentrancyGuard, Ownable
IERC20 tokenInContract = IERC20(tokenIn);

// Approve tokens for swap
tokenInContract.safeApprove(router, amountIn);
tokenInContract.approve(router, amountIn);

// Calculate minimum output with slippage protection
uint256 minAmountOut = amountIn - ((amountIn * slippageBps) / MAX_BPS);
Expand All @@ -422,7 +424,7 @@ contract ImprovedFlashArbitrage is IFlashLoanRecipient, ReentrancyGuard, Ownable
amountOut = ISwapRouter(router).exactInputSingle(swapParams);

// Reset approval for security
tokenInContract.safeApprove(router, 0);
tokenInContract.approve(router, 0);
}

/// @notice Updates contract statistics after successful arbitrage
Expand Down
40 changes: 30 additions & 10 deletions src/FlashArbitrageV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import {IQuoterV2} from "@uniswap/v3-periphery/contracts/interfaces/IQuoterV2.so
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";

/**
* @title ImprovedFlashArbitrage V3
Expand All @@ -34,8 +32,6 @@ import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
* @custom:optimization Advanced routing and gas optimization strategies
*/
contract ImprovedFlashArbitrageV3 is IFlashLoanRecipient, ReentrancyGuard, Ownable, Pausable {
using SafeERC20 for IERC20;

//////////////////////////////////////////////////////////////
// CONSTANTS //
//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -111,6 +107,15 @@ contract ImprovedFlashArbitrageV3 is IFlashLoanRecipient, ReentrancyGuard, Ownab
bytes[] extraData; // For protocol-specific parameters
}

/// @notice Parameters for advanced arbitrage execution
struct ArbitrageParamsV3 {
MultiFlashParams flashParams;
ArbitrageRoute buyRoute;
ArbitrageRoute sellRoute;
uint256 expectedProfit;
uint256 maxExecutionTime;
}

/// @notice Enhanced statistics with volatility tracking
struct StatisticsV3 {
uint256 totalTrades;
Expand Down Expand Up @@ -155,21 +160,36 @@ contract ImprovedFlashArbitrageV3 is IFlashLoanRecipient, ReentrancyGuard, Ownab
/// @notice Enhanced contract statistics
StatisticsV3 public stats;

/// @notice Circuit breaker state
CircuitBreaker public circuitBreaker;

/// @notice Mapping of authorized addresses
mapping(address => bool) public authorizedCallers;

/// @notice Tracks last execution block for MEV protection
mapping(address => uint256) public lastExecutionBlock;

/// @notice Price feed configurations by token
mapping(address => PriceFeedConfig) public priceFeeds;

/// @notice Supported DEX routers by protocol
mapping(DexProtocol => address[]) public dexRouters;

/// @notice Quoter addresses by protocol
mapping(DexProtocol => address) public quoters;

/// @notice Failed route tracking for optimization
mapping(bytes32 => uint256) public failedRoutes;

/// @notice Maximum gas price for execution
uint256 public maxGasPrice = 100 gwei;

/// @notice Dynamic profit multiplier for minimum profit calculation
uint256 public dynamicProfitMultiplier = BASE_MIN_PROFIT_BPS;

/// @notice Profit sharing configuration array
ProfitSharing[] public profitSharings;

//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -337,7 +357,7 @@ contract ImprovedFlashArbitrageV3 is IFlashLoanRecipient, ReentrancyGuard, Ownab
// Repay flash loans and calculate profits
uint256 totalProfit = 0;
for (uint256 i = 0; i < tokens.length; i++) {
tokens[i].safeTransfer(address(VAULT), amounts[i] + feeAmounts[i]);
tokens[i].transfer(address(VAULT), amounts[i] + feeAmounts[i]);

uint256 finalBalance = tokens[i].balanceOf(address(this));
if (finalBalance > initialBalances[i]) {
Expand Down Expand Up @@ -523,7 +543,7 @@ contract ImprovedFlashArbitrageV3 is IFlashLoanRecipient, ReentrancyGuard, Ownab
uint24 fee,
uint256 minAmountOut
) internal returns (uint256 amountOut) {
IERC20(tokenIn).safeApprove(router, amountIn);
IERC20(tokenIn).approve(router, amountIn);

ISwapRouter.ExactInputSingleParams memory swapParams = ISwapRouter.ExactInputSingleParams({
tokenIn: tokenIn,
Expand All @@ -537,7 +557,7 @@ contract ImprovedFlashArbitrageV3 is IFlashLoanRecipient, ReentrancyGuard, Ownab
});

amountOut = ISwapRouter(router).exactInputSingle(swapParams);
IERC20(tokenIn).safeApprove(router, 0);
IERC20(tokenIn).approve(router, 0);
}

/// @notice Distribute profits according to sharing configuration
Expand All @@ -547,7 +567,7 @@ contract ImprovedFlashArbitrageV3 is IFlashLoanRecipient, ReentrancyGuard, Ownab
for (uint256 i = 0; i < profitSharings.length; i++) {
uint256 share = (totalProfit * profitSharings[i].basisPoints) / MAX_BPS;
if (share > 0) {
IERC20(token).safeTransfer(profitSharings[i].recipient, share);
IERC20(token).transfer(profitSharings[i].recipient, share);
distributed += share;

emit ProfitShared(profitSharings[i].recipient, share, profitSharings[i].basisPoints);
Expand All @@ -557,7 +577,7 @@ contract ImprovedFlashArbitrageV3 is IFlashLoanRecipient, ReentrancyGuard, Ownab
// Send remainder to owner
uint256 remainder = totalProfit - distributed;
if (remainder > 0) {
IERC20(token).safeTransfer(owner(), remainder);
IERC20(token).transfer(owner(), remainder);
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/fork/PriceManipulationTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity 0.8.18;

import {Test, console} from "forge-std/Test.sol";
import {HelperConfig} from "../../script/HelperConfig.s.sol";
import {IERC20} from "@openzeppelin/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import {IQuoterV2} from "@uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol";

Expand Down
8 changes: 4 additions & 4 deletions test/unit/ArbitrageTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ pragma solidity 0.8.18;

import {Test, console} from "forge-std/Test.sol";
import {StdUtils} from "forge-std/StdUtils.sol";
import {FlashArbitrage} from "../../src/FlashArbitrage.sol";
import {Arbitrage} from "../../src/FlashArbitrage.sol";
import {HelperConfig} from "../../script/HelperConfig.s.sol";
import {IERC20} from "@openzeppelin/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";

contract ArbitrageTest is Test {
FlashArbitrage public arbitrage;
Arbitrage public arbitrage;
HelperConfig public helperConfig;
HelperConfig.ForkNetworkConfig public networkConfig;

Expand All @@ -28,7 +28,7 @@ contract ArbitrageTest is Test {
baseSepoliaFork = vm.createSelectFork(ETH_SEPOLIA_RPC_URL);

vm.startPrank(owner);
arbitrage = new FlashArbitrage();
arbitrage = new Arbitrage();
vm.stopPrank();

deal(networkConfig.usdc, owner, 69);
Expand Down
Loading