Arbitrage Engine
The Arbitrage Engine is the core contract responsible for executing cross-DEX arbitrage strategies. It handles opportunity detection, execution, and profit management.
Contract Overview
Opportunity Detection
Continuously scan DEXs for profitable price discrepancies
Atomic Execution
Execute buy and sell orders atomically to guarantee profit
Safety Checks
Multiple validation layers prevent loss-making trades
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/IDEX.sol";
import "./interfaces/IRouter.sol";
contract ArbitrageEngine is ReentrancyGuard, Ownable {
struct ArbitrageOpportunity {
address buyDex;
address sellDex;
address tokenA;
address tokenB;
uint256 profit;
uint256 minProfit;
}
// State variables
mapping(address => bool) public authorizedCallers;
uint256 public minProfitThreshold;
uint256 public maxSlippage;
address public poipoeToken;
event ArbitrageExecuted(
address indexed trader,
address buyDex,
address sellDex,
uint256 profit,
uint256 gasUsed
);
modifier onlyAuthorized() {
require(
authorizedCallers[msg.sender] || owner() == msg.sender,
"Unauthorized caller"
);
_;
}
function executeArbitrage(
ArbitrageOpportunity memory opportunity
) external onlyAuthorized nonReentrant {
require(
opportunity.profit >= minProfitThreshold,
"Insufficient profit"
);
// Pre-execution checks
require(
validateOpportunity(opportunity),
"Invalid opportunity"
);
// Estimate gas and ensure profitable after gas costs
uint256 gasStart = gasleft();
uint256 gasPrice = tx.gasprice;
// Execute buy on first DEX
uint256 tokenAAmount = IERC20(opportunity.tokenA).balanceOf(address(this));
require(
IUniswapV2Router(opportunity.buyDex).swapExactTokensForTokens(
tokenAAmount,
0, // Accept any amount of tokenB
getPath(opportunity.tokenA, opportunity.tokenB),
address(this),
block.timestamp + 300 // 5 minute deadline
).length > 0,
"Buy execution failed"
);
// Execute sell on second DEX
uint256 tokenBAmount = IERC20(opportunity.tokenB).balanceOf(address(this));
require(
IUniswapV2Router(opportunity.sellDex).swapExactTokensForTokens(
tokenBAmount,
0, // Accept any amount back
getPath(opportunity.tokenB, opportunity.tokenA),
address(this),
block.timestamp + 300
).length > 0,
"Sell execution failed"
);
// Calculate actual profit
uint256 finalTokenAAmount = IERC20(opportunity.tokenA).balanceOf(address(this));
require(finalTokenAAmount > tokenAAmount, "No profit achieved");
uint256 profit = finalTokenAAmount - tokenAAmount;
// Ensure still profitable after gas costs
uint256 gasUsed = gasStart - gasleft();
uint256 gasCost = gasUsed * gasPrice;
require(profit > gasCost, "Unprofitable after gas");
// Transfer profit
IERC20(opportunity.tokenA).transfer(msg.sender, profit);
emit ArbitrageExecuted(
msg.sender,
opportunity.buyDex,
opportunity.sellDex,
profit,
gasUsed
);
}
function validateOpportunity(ArbitrageOpportunity memory opportunity)
internal view returns (bool) {
// Check DEX addresses
require(
opportunity.buyDex != opportunity.sellDex,
"Same DEX"
);
// Check profit threshold
if (opportunity.profit < minProfitThreshold) {
return false;
}
// Additional validation logic here
return true;
}
}
Liquidation Manager
The Liquidation Manager coordinates liquidation strategies across multiple lending protocols, optimizing for profit while maintaining protocol health.
Protocol Integration
Monitor Positions
Continuously track health factors across integrated protocols
Calculate Profitable Liquidations
Assess liquidation bonuses against gas costs and competition
Execute with Optimization
Use gas optimization and timing to maximize liquidation success
Manage Seized Assets
Handle collateral and distribute profits to strategy participants
contract LiquidationManager is Ownable, Pausable {
struct ProtocolConfig {
address protocol;
uint256 bonusRate;
bool active;
}
mapping(address => ProtocolConfig) public protocols;
mapping(address => bool) public liquidators;
event LiquidationExecuted(
address indexed protocol,
address indexed borrower,
uint256 debtAmount,
uint256 bonusAmount
);
function liquidatePosition(
address protocol,
address borrower,
address collateralToken
) external whenNotPaused {
require(liquidators[msg.sender], "Unauthorized liquidator");
require(protocols[protocol].active, "Protocol not active");
ProtocolConfig memory config = protocols[protocol];
// Check if position is liquidatable
(
uint256 totalDebt,
uint256 totalCollateral,
uint256 healthFactor
) = ILendingProtocol(protocol).getPositionInfo(borrower);
require(healthFactor < 1e18, "Position not liquidatable");
// Calculate liquidation amount and bonus
uint256 maxLiquidation = ILendingProtocol(protocol)
.getMaxLiquidation(borrower, collateralToken);
require(maxLiquidation > 0, "No liquidatable amount");
// Execute liquidation
uint256 bonusAmount = (maxLiquidation * config.bonusRate) / 10000;
uint256 gasStart = gasleft();
ILendingProtocol(protocol).liquidate(borrower, maxLiquidation);
uint256 gasUsed = gasStart - gasleft();
// Distribute bonus to liquidator
IERC20(collateralToken).transfer(msg.sender, bonusAmount);
emit LiquidationExecuted(
protocol,
borrower,
maxLiquidation,
bonusAmount
);
}
function updateProtocolConfig(
address protocol,
uint256 newBonusRate,
bool active
) external onlyOwner {
protocols[protocol] = ProtocolConfig({
protocol: protocol,
bonusRate: newBonusRate,
active: active
});
}
}
Sandwich Detector
The Sandwich Detector identifies potential sandwich attack opportunities and executes them atomically to minimize MEV competition.
Pattern Recognition
Identifies large trades with significant price impact potential
Atomic Execution
Bundles all three transactions for guaranteed execution sequence
Profit Calculation
Calculates expected profit after gas costs and slippage
Risk Manager
The Risk Manager implements circuit breakers, position limits, and emergency controls to protect the protocol and user funds.
Risk Controls
Circuit Breakers
Automatically pause trading during high volatility or unusual activity
Position Limits
Enforce maximum position sizes to prevent concentration risk
Emergency Controls
Manual override capabilities for critical situations
contract RiskManager is Pausable, Ownable {
struct RiskParams {
uint256 maxPositionSize;
uint256 maxDailyVolume;
uint256 minProfitThreshold;
uint256 maxSlippage;
}
struct DailyStats {
uint256 volume;
uint256 profit;
uint256 transactions;
}
mapping(address => RiskParams) public traderParams;
mapping(address => DailyStats) public dailyStats;
mapping(address => uint256) public lastResetDate;
uint256 public maxDailyLoss;
uint256 public currentDailyLoss;
uint256 public lossTriggerThreshold;
event PositionLimited(address indexed trader, uint256 attempted, uint256 allowed);
event RiskBreach(string reason, address indexed trader);
event EmergencyStop(address indexed operator, string reason);
function validateTrade(address trader, uint256 size, uint256 profit)
external view returns (bool, string memory) {
// Check circuit breaker
if (paused()) {
return (false, "Trading paused");
}
// Check position size
if (size > traderParams[trader].maxPositionSize) {
return (false, "Position too large");
}
// Check daily volume
resetDailyStatsIfNeeded(trader);
if (dailyStats[trader].volume + size > traderParams[trader].maxDailyVolume) {
return (false, "Daily volume limit exceeded");
}
// Check profit threshold
if (profit < traderParams[trader].minProfitThreshold) {
return (false, "Insufficient profit");
}
// Check loss limits
if (currentDailyLoss > lossTriggerThreshold) {
return (false, "Loss limit exceeded");
}
return (true, "");
}
function recordTrade(address trader, uint256 size, int256 profit)
external onlyAuthorized {
resetDailyStatsIfNeeded(trader);
dailyStats[trader].volume += size;
dailyStats[trader].transactions += 1;
if (profit < 0) {
currentDailyLoss += uint256(-profit);
} else {
dailyStats[trader].profit += uint256(profit);
}
}
function emergencyStop(string memory reason) external onlyOwner {
_pause();
emit EmergencyStop(msg.sender, reason);
}
}
Flashloan Hub
The Flashloan Hub provides flashloan functionality from multiple protocols, enabling capital-efficient MEV strategies.
Protocol Support
Aave Integration
Access to Aave's extensive flashloan pool across multiple assets
dYdX Support
Flashloans from dYdX's margin trading platform
Balancer Pools
Access to Balancer's weighted pool flashloans
Access Control
Comprehensive access control system ensuring only authorized contracts and addresses can interact with critical functions.
Role-Based Permissions
Owner
Full control over contract parameters and emergency functions
Operator
Manage day-to-day operations and risk parameters
Bot
Execute trading strategies within defined parameters
Upgradability
Proxy-based upgradability allows for protocol improvements and bug fixes while maintaining state and security.
Audit Results
All PoIPoE contracts have been thoroughly audited by leading security firms to ensure maximum safety and reliability.
Security Audits
ConsenSys Diligence
Comprehensive security audit with zero critical findings
CertiK Verification
Formal verification of critical contract logic
Trail of Bits
Advanced static analysis and security testing