Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AaveFlashArbitrageV4
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
// =============================================================================
// AAVE FLASH ARBITRAGE V4 - BALANCER V2 FLASH LOANS + UNISWAP V3 SWAPS
// =============================================================================
//
// V4 Changes from V3:
// - Uses Balancer V2 flashLoan() instead of V3 unlock() (permissionless, 0% fee!)
// - Uniswap V3 multi-hop for GHO↔AAVE swaps (replaces dead Balancer pools)
// - Based on working VLRFlashArbitrageV3 pattern
//
// Architecture:
// - Flash Loans: Balancer V2 (receiveFlashLoan callback, 0% fee)
// - Outcome Swaps: Uniswap V3 (YES_AAVE/YES_GHO, NO_AAVE/NO_GHO pools)
// - Repayment Swaps: Uniswap V3 multi-hop (GHO→USDC→WETH→AAVE)
// =============================================================================
// =============================================================================
// INTERFACES
// =============================================================================
interface IBalancerV2Vault {
function flashLoan(
address recipient,
IERC20[] memory tokens,
uint256[] memory amounts,
bytes memory userData
) external;
}
interface ISwapRouter {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
}
interface IFutarchyRouter {
function splitPosition(address proposal, address collateralToken, uint256 amount) external;
function mergePositions(address proposal, address collateralToken, uint256 amount) external;
}
interface IFutarchyProposal {
function collateralToken1() external view returns (IERC20);
function collateralToken2() external view returns (IERC20);
function wrappedOutcome(uint256 index) external view returns (IERC20 wrapped1155, bytes memory data);
}
// =============================================================================
// CONTRACT
// =============================================================================
/**
* @title AaveFlashArbitrageV4
* @notice Flash arbitrage for AAVE/GHO markets using Balancer V2 flash loans
* @dev
* V4 Improvements:
* - Balancer V2 flash loans (permissionless, 0% fee!)
* - Uniswap V3 multi-hop paths for GHO↔AAVE (replaces dead Balancer pools)
* - minProfit MEV protection
*
* Strategies:
* - SPOT_SPLIT (0): Borrow AAVE → Split → Swap to GHO outcomes → Merge to GHO → Swap back to AAVE
* - MERGE_SPOT (1): Borrow AAVE → Swap to GHO → Split → Swap to AAVE outcomes → Merge to AAVE
*/
contract AaveFlashArbitrageV4 is ReentrancyGuard {
using SafeERC20 for IERC20;
// ==========================================================================
// CONSTANTS (Mainnet)
// ==========================================================================
address public constant AAVE = 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9;
address public constant GHO = 0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f;
address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
// Balancer V2 Vault (0% flash loan fee!)
IBalancerV2Vault public constant balancerVault = IBalancerV2Vault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
// Uniswap V3 SwapRouter
ISwapRouter public constant swapRouter = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
// Futarchy Router (Mainnet - same as VLR contract)
IFutarchyRouter public constant futarchyRouter = IFutarchyRouter(0xAc9Bf8EbA6Bd31f8E8c76f8E8B2AAd0BD93f98Dc);
// Uniswap V3 fee tiers
uint24 public constant FEE_LOWEST = 100; // 0.01%
uint24 public constant FEE_LOW = 500; // 0.05%
uint24 public constant FEE_MEDIUM = 3000; // 0.30%
uint24 public constant FEE_HIGH = 10000; // 1.00%
address public admin;
// ==========================================================================
// STRUCTS & ENUMS
// ==========================================================================
enum ArbitrageDirection { SPOT_SPLIT, MERGE_SPOT }
struct ProposalInfo {
address proposal;
address yesAave;
address noAave;
address yesGho;
address noGho;
bool isValid;
}
struct ArbitrageResult {
bool success;
uint256 profit;
uint256 borrowAmount;
uint256 gasUsed;
}
struct ArbitrageParams {
address proposal;
ArbitrageDirection direction;
uint256 minProfit;
}
// Transient state for callback
ArbitrageParams private _params;
address private _profitRecipient;
ArbitrageResult private _lastResult;
// ==========================================================================
// EVENTS (for debugging)
// ==========================================================================
event ArbitrageStarted(
address indexed caller,
address indexed proposal,
ArbitrageDirection direction,
uint256 borrowAmount
);
event SwapExecuted(
string step,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOut
);
event SplitExecuted(address token, uint256 amount);
event MergeExecuted(address token, uint256 amount);
event ArbitrageCompleted(
address indexed caller,
uint256 profit,
uint256 borrowAmount,
uint256 gasUsed
);
error ArbitrageFailed(uint256 balanceAfter, uint256 required, string reason);
error InsufficientProfit(uint256 actual, uint256 minimum);
error InvalidProposal(address proposal);
// ==========================================================================
// CONSTRUCTOR
// ==========================================================================
constructor() {
admin = msg.sender;
// Pre-approve tokens to SwapRouter
IERC20(AAVE).approve(address(swapRouter), type(uint256).max);
IERC20(GHO).approve(address(swapRouter), type(uint256).max);
IERC20(USDC).approve(address(swapRouter), type(uint256).max);
IERC20(WETH).approve(address(swapRouter), type(uint256).max);
// Pre-approve to FutarchyRouter
IERC20(AAVE).approve(address(futarchyRouter), type(uint256).max);
IERC20(GHO).approve(address(futarchyRouter), type(uint256).max);
}
// ==========================================================================
// EXTERNAL: EXECUTE ARBITRAGE
// ==========================================================================
/**
* @notice Execute flash arbitrage
* @param proposalAddress Futarchy proposal address
* @param borrowAmount Amount to flash borrow (in AAVE)
* @param direction SPOT_SPLIT (0) or MERGE_SPOT (1)
* @param minProfit Minimum profit required (MEV protection)
* @return result Arbitrage result
*/
function executeArbitrage(
address proposalAddress,
uint256 borrowAmount,
ArbitrageDirection direction,
uint256 minProfit
) external nonReentrant returns (ArbitrageResult memory result) {
uint256 gasStart = gasleft();
emit ArbitrageStarted(msg.sender, proposalAddress, direction, borrowAmount);
// Store params for callback
_params = ArbitrageParams({
proposal: proposalAddress,
direction: direction,
minProfit: minProfit
});
_profitRecipient = msg.sender;
// Flash Loan via Balancer V2 (0% fee!)
IERC20[] memory tokens = new IERC20[](1);
tokens[0] = IERC20(AAVE);
uint256[] memory amounts = new uint256[](1);
amounts[0] = borrowAmount;
balancerVault.flashLoan(address(this), tokens, amounts, abi.encode(_params));
result = _lastResult;
result.gasUsed = gasStart - gasleft();
emit ArbitrageCompleted(msg.sender, result.profit, result.borrowAmount, result.gasUsed);
return result;
}
// ==========================================================================
// BALANCER V2 CALLBACK
// ==========================================================================
function receiveFlashLoan(
IERC20[] memory,
uint256[] memory amounts,
uint256[] memory feeAmounts,
bytes memory userData
) external {
require(msg.sender == address(balancerVault), "Only Balancer Vault");
ArbitrageParams memory params = abi.decode(userData, (ArbitrageParams));
uint256 borrowAmount = amounts[0];
uint256 repayAmount = borrowAmount + feeAmounts[0]; // feeAmount is 0 for Balancer V2!
// Load proposal
ProposalInfo memory info = _loadProposal(params.proposal);
if (!info.isValid) {
revert InvalidProposal(params.proposal);
}
// Approve outcome tokens to SwapRouter (dynamic)
_approveIfNeeded(info.yesAave, address(swapRouter));
_approveIfNeeded(info.noAave, address(swapRouter));
_approveIfNeeded(info.yesGho, address(swapRouter));
_approveIfNeeded(info.noGho, address(swapRouter));
// Approve outcome tokens to FutarchyRouter
_approveIfNeeded(info.yesAave, address(futarchyRouter));
_approveIfNeeded(info.noAave, address(futarchyRouter));
_approveIfNeeded(info.yesGho, address(futarchyRouter));
_approveIfNeeded(info.noGho, address(futarchyRouter));
// Execute strategy
if (params.direction == ArbitrageDirection.SPOT_SPLIT) {
_executeSpotSplit(info, borrowAmount);
} else {
_executeMergeSpot(info, borrowAmount);
}
// Check balance and profit
uint256 aaveBalance = IERC20(AAVE).balanceOf(address(this));
if (aaveBalance < repayAmount) {
revert ArbitrageFailed(aaveBalance, repayAmount, "Insufficient to repay");
}
uint256 profit = aaveBalance - repayAmount;
if (profit < params.minProfit) {
revert InsufficientProfit(profit, params.minProfit);
}
// Repay flash loan
IERC20(AAVE).transfer(address(balancerVault), repayAmount);
// Send profit to caller
if (profit > 0) {
IERC20(AAVE).safeTransfer(_profitRecipient, profit);
}
_lastResult = ArbitrageResult({
success: true,
profit: profit,
borrowAmount: borrowAmount,
gasUsed: 0
});
}
// ==========================================================================
// STRATEGY: SPOT_SPLIT
// ==========================================================================
// 1. Split AAVE → YES_AAVE + NO_AAVE
// 2. Swap YES_AAVE → YES_GHO
// 3. Swap NO_AAVE → NO_GHO
// 4. Merge YES_GHO + NO_GHO → GHO
// 5. Swap GHO → AAVE (via USDC → WETH → AAVE)
function _executeSpotSplit(ProposalInfo memory info, uint256 amount) internal {
// 1. Split
futarchyRouter.splitPosition(info.proposal, AAVE, amount);
emit SplitExecuted(AAVE, amount);
// 2. Swap YES_AAVE → YES_GHO
uint256 yesAaveBal = IERC20(info.yesAave).balanceOf(address(this));
if (yesAaveBal > 0) {
uint256 out = _swapSingle(info.yesAave, info.yesGho, FEE_LOW, yesAaveBal);
emit SwapExecuted("YES_AAVE->YES_GHO", info.yesAave, info.yesGho, yesAaveBal, out);
}
// 3. Swap NO_AAVE → NO_GHO
uint256 noAaveBal = IERC20(info.noAave).balanceOf(address(this));
if (noAaveBal > 0) {
uint256 out = _swapSingle(info.noAave, info.noGho, FEE_LOW, noAaveBal);
emit SwapExecuted("NO_AAVE->NO_GHO", info.noAave, info.noGho, noAaveBal, out);
}
// 4. Merge
uint256 yesGhoBal = IERC20(info.yesGho).balanceOf(address(this));
uint256 noGhoBal = IERC20(info.noGho).balanceOf(address(this));
uint256 mergeAmount = yesGhoBal < noGhoBal ? yesGhoBal : noGhoBal;
if (mergeAmount > 0) {
futarchyRouter.mergePositions(info.proposal, GHO, mergeAmount);
emit MergeExecuted(GHO, mergeAmount);
}
// 5. Swap GHO → AAVE (multi-hop via USDC → WETH)
uint256 ghoBal = IERC20(GHO).balanceOf(address(this));
if (ghoBal > 0) {
uint256 out = _swapGhoToAave(ghoBal);
emit SwapExecuted("GHO->AAVE", GHO, AAVE, ghoBal, out);
}
}
// ==========================================================================
// STRATEGY: MERGE_SPOT
// ==========================================================================
// 1. Swap AAVE → GHO (via WETH → USDC → GHO)
// 2. Split GHO → YES_GHO + NO_GHO
// 3. Swap YES_GHO → YES_AAVE
// 4. Swap NO_GHO → NO_AAVE
// 5. Merge YES_AAVE + NO_AAVE → AAVE
function _executeMergeSpot(ProposalInfo memory info, uint256 amount) internal {
// 1. Swap AAVE → GHO
uint256 ghoReceived = _swapAaveToGho(amount);
emit SwapExecuted("AAVE->GHO", AAVE, GHO, amount, ghoReceived);
// 2. Split GHO
futarchyRouter.splitPosition(info.proposal, GHO, ghoReceived);
emit SplitExecuted(GHO, ghoReceived);
// 3. Swap YES_GHO → YES_AAVE
uint256 yesGhoBal = IERC20(info.yesGho).balanceOf(address(this));
if (yesGhoBal > 0) {
uint256 out = _swapSingle(info.yesGho, info.yesAave, FEE_LOW, yesGhoBal);
emit SwapExecuted("YES_GHO->YES_AAVE", info.yesGho, info.yesAave, yesGhoBal, out);
}
// 4. Swap NO_GHO → NO_AAVE
uint256 noGhoBal = IERC20(info.noGho).balanceOf(address(this));
if (noGhoBal > 0) {
uint256 out = _swapSingle(info.noGho, info.noAave, FEE_LOW, noGhoBal);
emit SwapExecuted("NO_GHO->NO_AAVE", info.noGho, info.noAave, noGhoBal, out);
}
// 5. Merge
uint256 yesAaveBal = IERC20(info.yesAave).balanceOf(address(this));
uint256 noAaveBal = IERC20(info.noAave).balanceOf(address(this));
uint256 mergeAmount = yesAaveBal < noAaveBal ? yesAaveBal : noAaveBal;
if (mergeAmount > 0) {
futarchyRouter.mergePositions(info.proposal, AAVE, mergeAmount);
emit MergeExecuted(AAVE, mergeAmount);
}
}
// ==========================================================================
// SWAP HELPERS (UNISWAP V3)
// ==========================================================================
/**
* @dev Single-hop Uniswap V3 swap
*/
function _swapSingle(
address tokenIn,
address tokenOut,
uint24 fee,
uint256 amountIn
) internal returns (uint256 amountOut) {
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
fee: fee,
recipient: address(this),
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0, // Rely on minProfit check
sqrtPriceLimitX96: 0
});
return swapRouter.exactInputSingle(params);
}
/**
* @dev Multi-hop: GHO → USDC (0.01%) → WETH (0.05%) → AAVE (0.3%)
*/
function _swapGhoToAave(uint256 amountIn) internal returns (uint256 amountOut) {
bytes memory path = abi.encodePacked(
GHO, FEE_LOWEST, // GHO → USDC (0.01%)
USDC, FEE_LOW, // USDC → WETH (0.05%)
WETH, FEE_MEDIUM, // WETH → AAVE (0.3%)
AAVE
);
ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({
path: path,
recipient: address(this),
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0 // Rely on minProfit check
});
return swapRouter.exactInput(params);
}
/**
* @dev Multi-hop: AAVE → WETH (0.3%) → USDC (0.05%) → GHO (0.01%)
*/
function _swapAaveToGho(uint256 amountIn) internal returns (uint256 amountOut) {
bytes memory path = abi.encodePacked(
AAVE, FEE_MEDIUM, // AAVE → WETH (0.3%)
WETH, FEE_LOW, // WETH → USDC (0.05%)
USDC, FEE_LOWEST, // USDC → GHO (0.01%)
GHO
);
ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({
path: path,
recipient: address(this),
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0 // Rely on minProfit check
});
return swapRouter.exactInput(params);
}
// ==========================================================================
// UTILS
// ==========================================================================
function _loadProposal(address proposalAddr) internal view returns (ProposalInfo memory info) {
IFutarchyProposal proposal = IFutarchyProposal(proposalAddr);
info.proposal = proposalAddr;
address col1 = address(proposal.collateralToken1());
address col2 = address(proposal.collateralToken2());
// Validate AAVE/GHO market
bool validPair = (col1 == AAVE && col2 == GHO) || (col1 == GHO && col2 == AAVE);
if (!validPair) return info;
info.isValid = true;
// Load outcome tokens
(IERC20 y0,) = proposal.wrappedOutcome(0);
(IERC20 n0,) = proposal.wrappedOutcome(1);
(IERC20 y1,) = proposal.wrappedOutcome(2);
(IERC20 n1,) = proposal.wrappedOutcome(3);
if (col1 == AAVE) {
info.yesAave = address(y0);
info.noAave = address(n0);
info.yesGho = address(y1);
info.noGho = address(n1);
} else {
info.yesGho = address(y0);
info.noGho = address(n0);
info.yesAave = address(y1);
info.noAave = address(n1);
}
}
function _approveIfNeeded(address token, address spender) internal {
if (IERC20(token).allowance(address(this), spender) == 0) {
IERC20(token).approve(spender, type(uint256).max);
}
}
// ==========================================================================
// ADMIN
// ==========================================================================
function recoverTokens(address token, uint256 amount) external {
require(msg.sender == admin, "Admin only");
IERC20(token).safeTransfer(admin, amount);
}
function transferAdmin(address newAdmin) external {
require(msg.sender == admin, "Admin only");
require(newAdmin != address(0), "Invalid admin");
admin = newAdmin;
}
receive() external payable {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"balanceAfter","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"},{"internalType":"string","name":"reason","type":"string"}],"name":"ArbitrageFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"minimum","type":"uint256"}],"name":"InsufficientProfit","type":"error"},{"inputs":[{"internalType":"address","name":"proposal","type":"address"}],"name":"InvalidProposal","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"profit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"}],"name":"ArbitrageCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"proposal","type":"address"},{"indexed":false,"internalType":"enum AaveFlashArbitrageV4.ArbitrageDirection","name":"direction","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"borrowAmount","type":"uint256"}],"name":"ArbitrageStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MergeExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SplitExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"step","type":"string"},{"indexed":false,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"SwapExecuted","type":"event"},{"inputs":[],"name":"AAVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_HIGH","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_LOW","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_LOWEST","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_MEDIUM","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GHO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balancerVault","outputs":[{"internalType":"contract IBalancerV2Vault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proposalAddress","type":"address"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"internalType":"enum AaveFlashArbitrageV4.ArbitrageDirection","name":"direction","type":"uint8"},{"internalType":"uint256","name":"minProfit","type":"uint256"}],"name":"executeArbitrage","outputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"profit","type":"uint256"},{"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"internalType":"struct AaveFlashArbitrageV4.ArbitrageResult","name":"result","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"futarchyRouter","outputs":[{"internalType":"contract IFutarchyRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"feeAmounts","type":"uint256[]"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"receiveFlashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapRouter","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"transferAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060409080825234620002b1576001600081815581546001600160a01b031916331790915563095ea7b360e01b80835273e592427a0aece92de3edee1f18e0157c0586156460048085018290526000196024808701829052602096737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9969593946044949390929091898187818b8d5af1801562000215576200028f575b50895192848452808785015282828501527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f938a8188818c895af1801562000263576200026d575b508a51858152818882015283838201528a8188818c73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb485af18015620002635762000241575b508a5190858252878201528282820152898187818b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af1801562000215576200021f575b508951848152898187818b73ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc9d8e8d84015288888401525af180156200021557918893918b9897969593620001f3575b508b51998a97889687528601528401525af1908115620001e85750620001b3575b82516123c290816200030b8239f35b81620001d792903d10620001e0575b620001ce8183620002b6565b810190620002f0565b503880620001a4565b503d620001c2565b8451903d90823e3d90fd5b6200020d90893d8b11620001e057620001ce8183620002b6565b503862000183565b8b513d8a823e3d90fd5b62000239908a3d8c11620001e057620001ce8183620002b6565b50386200013f565b6200025b908b3d8d11620001e057620001ce8183620002b6565b503862000106565b8c513d8b823e3d90fd5b62000287908b3d8d11620001e057620001ce8183620002b6565b5038620000cd565b620002a9908a3d8c11620001e057620001ce8183620002b6565b503862000091565b600080fd5b601f909101601f19168101906001600160401b03821190821017620002da57604052565b634e487b7160e01b600052604160045260246000fd5b90816020910312620002b157518015158103620002b1579056fe6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c8063069c9fae146119f15780630db188b1146119c2578063158274a5146119935780633add5c051461197657806348ccda3c1461194757806363075eb91461192a57806375829def146118a857806379dc9b321461188c57806389a302711461185d578063ad5c46481461182e578063b8d008f3146117ff578063c31c9c07146117d0578063ca216247146117b3578063f04f270714610464578063f3df2206146101025763f851a440146100d7575061000e565b346100ff57806003193601126100ff576001546040516001600160a01b039091168152602090f35b80fd5b50346100ff5760803660031901126100ff5761011c611a9b565b90604435602435600282101561046057606435906040519261013d84611b13565b84845284602085015284604085015284606080950152600285541461044e57600285555a60405190966001600160a01b03169190829061017d8184611c98565b8460208201527f6d46a9b7d1eee35a4a05f88046aeab446fa24dc8498c02f6c70f4bbfd684910e60403392a383604080516101b781611ab1565b8481528360208201520152816002549160ff60a01b9060a01b16916affffffffffffffffffffff60a81b1617178060025583600355336bffffffffffffffffffffffff60a01b60045416176004556040519361021285611b2f565b6001855261027d60208601926020368537737fc66500c84a76ad7e9c93437bfc5ac33e2ddae961024188611c3a565b526040519561024f87611b2f565b600187526020368189013761026387611c3a565b5260405194602086015260ff604086019160a01c16611c98565b8583015284825261028d82611b13565b73ba12222222228d8ba445958a75a0704d566bf2c83b1561044a57604051632e1c224f60e11b815230600482015260806024820152935160848501819052869385939092909160a485019190865b8181106104255750505060031984820301604485015260208084519283815201930190855b81811061040957505050828203600319016064840152829161032191611cde565b03818373ba12222222228d8ba445958a75a0704d566bf2c85af180156103fe576103e6575b506080926040519261035784611b13565b60ff6005541615158452600654602085019081526001600754926040870193845261038c600854958789019687525a90611c5d565b8086528351908551604051928352602083015260408201527f9348050869e3b84bcf0cf6e185f0f61f5b26d21989f1160a65a95bf52090db39873392a2556040519451151585525160208501525160408401525190820152f35b6103f08391611aff565b6103fa5738610346565b5080fd5b6040513d85823e3d90fd5b8251855289965087955060209485019490920191600101610300565b82516001600160a01b031684528a9750889650602093840193909201916001016102db565b8580fd5b604051633ee5aeb560e01b8152600490fd5b8280fd5b50346100ff5760803660031901126100ff5767ffffffffffffffff600435818111610460573660238201121561046057806004013590602460206104a784611b6d565b6104b46040519182611b4b565b848152019260051b82010190368211610e2857602401915b81831061179357505050602435818111610460576104ee903690600401611b85565b9060443581811161178f57610507903690600401611b85565b9160643591821161178f573660238301121561178f578160040135918461052d84611be5565b9161053b6040519384611b4b565b84835260208301943660248284010111610460578060246020930187378301015273ba12222222228d8ba445958a75a0704d566bf2c8330361175457606081805181010312610e28576040519261059184611ab1565b516001600160a01b038116810361044a578352604081015191600283101561044a5760606105ce926105d594602087015201516040850152611c3a565b5192611c3a565b5182018083116117405781516105f3906001600160a01b0316611d88565b60a08101511561171c576020810151610614906001600160a01b03166120cc565b604081015161062b906001600160a01b03166120cc565b6060810151610642906001600160a01b03166120cc565b6080810151610659906001600160a01b03166120cc565b6020810151610670906001600160a01b03166121a5565b6040810151610687906001600160a01b03166121a5565b606081015161069e906001600160a01b03166121a5565b60808101516106b5906001600160a01b03166121a5565b602083015160028110156117085761104b57805185906001600160a01b031673ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b156103fa57604051906301abf04560e71b82526004820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9602482015285604482015281816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af18015610e2c57611037575b50507f0d25117aca3bb15ab1bf182fe0905dfe8cb4185e0009febe06820439b337c98460408051737fc66500c84a76ad7e9c93437bfc5ac33e2ddae98152866020820152a16020818101516040516370a0823160e01b81523060048201529190829060249082906001600160a01b03165afa908115610a93578691611005575b5080610f6f575b5060408181015190516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa908115610a93578691610f3d575b5080610ea9575b5060608101516040516370a0823160e01b81523060048201528691602090829060249082906001600160a01b03165afa908115610e2c578291610e74575b5060808301516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103fe578391610e3f575b5080821015610e375750915b82610d46575b50506040516370a0823160e01b815230600482015290506020816024817340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f5afa908115610d3b578591610d09575b5080610b3c575b505b6040516370a0823160e01b8152306004820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae99190602081602481865afa908115610a93578691610b05575b50818110610abc5761094282604092611c5d565b930151808410610a9e575060405163a9059cbb60e01b9182825273ba12222222228d8ba445958a75a0704d566bf2c86004830152602482015260208160448189875af18015610a9357610a64575b50826109d4575b50508260606040516109a881611b13565b600181528360208201528460408201520152600160ff1960055416176005556006556007558060085580f35b60045460405160208082019384526001600160a01b039092166024820152604481018590529091600091610a1581606481015b03601f198101835282611b4b565b519082855af115610a58576000513d610a4f5750803b155b610a375780610997565b60249060405190635274afe760e01b82526004820152fd5b60011415610a2d565b6040513d6000823e3d90fd5b610a859060203d602011610a8c575b610a7d8183611b4b565b810190611c80565b5038610990565b503d610a73565b6040513d88823e3d90fd5b8360449160405191632744211560e11b835260048301526024820152fd5b60a49160405191633566cf0d60e01b835260048301526024820152606060448201526015606482015274496e73756666696369656e7420746f20726570617960581b6084820152fd5b90506020813d602011610b34575b81610b2060209383611b4b565b81010312610b2f57513861092e565b600080fd5b3d9150610b13565b6040517340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f60601b602082810191909152601960ea1b60348301527314170d3238c43166d83a33a945d3d619c6c0dd6960631b6037830152607d60ea1b604b830152736015551cd911ff4685072e2793f56c841e3ab66160611b604e83015261017760eb1b6062830152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae960601b606583015260598252610c2791610be781611b13565b60405190610bf482611ae3565b815230828201524260408201528360608201528760808201526040518093819263c04b8d5960e01b835260048301612202565b03818973e592427a0aece92de3edee1f18e0157c058615645af1908115610a93578691610cc9575b5060008051602061236d8339815191529160e0916040519160a08352600960a08401526847484f2d3e4141564560b81b60c08401527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6020840152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9604084015260608301526080820152a1386108eb565b90506020813d602011610d01575b81610ce460209383611b4b565b81010312610b2f575160008051602061236d833981519152610c4f565b3d9150610cd7565b90506020813d602011610d33575b81610d2460209383611b4b565b81010312610b2f5751386108e4565b3d9150610d17565b6040513d87823e3d90fd5b516001600160a01b031673ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b156103fa5760405190637abef8d160e01b825260048201527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f602482015282604482015281816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af18015610e2c57610e14575b505060407ff5bce2baecfbac717c0870301a2421776917796f559e40b2879651e7b88cf300918151907340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f82526020820152a13884816108a2565b610e1d90611aff565b610e28578438610dc6565b8480fd5b6040513d84823e3d90fd5b90509161089c565b9250506020823d602011610e6c575b81610e5b60209383611b4b565b81010312610b2f5786915138610890565b3d9150610e4e565b9150506020813d602011610ea1575b81610e9060209383611b4b565b81010312610b2f5785905138610853565b3d9150610e83565b6040820151608083015160008051602061236d8339815191529260e0929091610ee09183916001600160a01b03908116911661224c565b60018060a01b036040860151169160018060a01b036080870151166040519360a08552600f60a08601526e4e4f5f414156452d3e4e4f5f47484f60881b60c08601526020850152604084015260608301526080820152a138610815565b90506020813d602011610f67575b81610f5860209383611b4b565b81010312610b2f57513861080e565b3d9150610f4b565b6020820151606083015160008051602061236d8339815191529260e0929091610fa69183916001600160a01b03908116911661224c565b60018060a01b036020860151169160018060a01b036060870151166040519360a08552601160a0860152705945535f414156452d3e5945535f47484f60781b60c08601526020850152604084015260608301526080820152a1386107d1565b90506020813d60201161102f575b8161102060209383611b4b565b81010312610b2f5751386107ca565b3d9150611013565b61104090611aff565b610e2857843861074a565b604051737fc66500c84a76ad7e9c93437bfc5ac33e2ddae960601b60208281019190915261017760eb1b6034830152736015551cd911ff4685072e2793f56c841e3ab66160611b6037830152607d60ea1b604b8301527314170d3238c43166d83a33a945d3d619c6c0dd6960631b604e830152601960ea1b60628301527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f60601b606583015260598252611136916110f681611b13565b6040519061110382611ae3565b815230828201524260408201528660608201528760808201526040518093819263c04b8d5960e01b835260048301612202565b03818973e592427a0aece92de3edee1f18e0157c058615645af1908115610a935786916116d6575b5060008051602061236d83398151915260e060405160a08152600960a082015268414156452d3e47484f60b81b60c0820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae960208201527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6040820152876060820152836080820152a181516001600160a01b031673ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b156116d257604051906301abf04560e71b825260048201527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f602482015281604482015286816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af180156116c757611691575b5060407f0d25117aca3bb15ab1bf182fe0905dfe8cb4185e0009febe06820439b337c984918151907340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f82526020820152a160608101516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa908115610a9357869161165f575b50806115c9575b5060808101516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa908115610a93578691611597575b5080611507575b506020818101516040516370a0823160e01b815230600482015287929091829060249082906001600160a01b03165afa908115610e2c5782916114d2575b5060408381015190516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103fe57839161149d575b50808210156114955750915b826113b3575b5050506108ed565b516001600160a01b031673ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b156103fa5760405190637abef8d160e01b82526004820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9602482015282604482015281816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af18015610e2c57611481575b505060407ff5bce2baecfbac717c0870301a2421776917796f559e40b2879651e7b88cf30091815190737fc66500c84a76ad7e9c93437bfc5ac33e2ddae982526020820152a13884816113ab565b61148a90611aff565b610e28578438611433565b9050916113a5565b9250506020823d6020116114ca575b816114b960209383611b4b565b81010312610b2f5786915138611399565b3d91506114ac565b9150506020813d6020116114ff575b816114ee60209383611b4b565b81010312610b2f578590513861135c565b3d91506114e1565b6080820151604083015160008051602061236d8339815191529260e092909161153e9183916001600160a01b03908116911661224c565b608085810151604080880151815160a0808252600f908201526e4e4f5f47484f2d3e4e4f5f4141564560881b60c08201526001600160a01b0393841660208201529216908201526060810193909352820152a13861131e565b90506020813d6020116115c1575b816115b260209383611b4b565b81010312610b2f575138611317565b3d91506115a5565b6060820151602083015160008051602061236d8339815191529260e09290916116009183916001600160a01b03908116911661224c565b60018060a01b036060860151169160018060a01b036020870151166040519360a08552601160a0860152705945535f47484f2d3e5945535f4141564560781b60c08601526020850152604084015260608301526080820152a1386112da565b90506020813d602011611689575b8161167a60209383611b4b565b81010312610b2f5751386112d3565b3d915061166d565b7f0d25117aca3bb15ab1bf182fe0905dfe8cb4185e0009febe06820439b337c98491966116bf604092611aff565b969150611252565b6040513d89823e3d90fd5b8680fd5b90506020813d602011611700575b816116f160209383611b4b565b8101031261044a57513861115e565b3d91506116e4565b634e487b7160e01b86526021600452602486fd5b8251604051630aa7327760e31b81526001600160a01b039091166004820152602490fd5b634e487b7160e01b84526011600452602484fd5b60405162461bcd60e51b815260206004820152601360248201527213db9b1e4810985b185b98d95c8815985d5b1d606a1b6044820152606490fd5b8380fd5b82356001600160a01b038116810361044a578152602092830192016104cc565b50346100ff57806003193601126100ff576020604051610bb88152f35b50346100ff57806003193601126100ff57602060405173e592427a0aece92de3edee1f18e0157c058615648152f35b50346100ff57806003193601126100ff5760206040517340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f8152f35b50346100ff57806003193601126100ff57602060405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28152f35b50346100ff57806003193601126100ff57602060405173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488152f35b50346100ff57806003193601126100ff57602060405160648152f35b50346100ff5760203660031901126100ff576118c2611a9b565b600154906001600160a01b03906118dc3383851614611c01565b169081156118f5576001600160a01b0319161760015580f35b60405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21030b236b4b760991b6044820152606490fd5b50346100ff57806003193601126100ff5760206040516127108152f35b50346100ff57806003193601126100ff576020604051737fc66500c84a76ad7e9c93437bfc5ac33e2ddae98152f35b50346100ff57806003193601126100ff5760206040516101f48152f35b50346100ff57806003193601126100ff57602060405173ba12222222228d8ba445958a75a0704d566bf2c88152f35b50346100ff57806003193601126100ff57602060405173ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc8152f35b50346100ff5760403660031901126100ff57611a0b611a9b565b6001546001600160a01b03908116916020918491611a2a338614611c01565b60405163a9059cbb60e01b8582019081526001600160a01b0390961660248083019190915235604482015291169390611a668160648101610a07565b519082855af115611a8e5781513d611a855750803b155b610a37575080f35b60011415611a7d565b50604051903d90823e3d90fd5b600435906001600160a01b0382168203610b2f57565b6060810190811067ffffffffffffffff821117611acd57604052565b634e487b7160e01b600052604160045260246000fd5b60a0810190811067ffffffffffffffff821117611acd57604052565b67ffffffffffffffff8111611acd57604052565b6080810190811067ffffffffffffffff821117611acd57604052565b6040810190811067ffffffffffffffff821117611acd57604052565b90601f8019910116810190811067ffffffffffffffff821117611acd57604052565b67ffffffffffffffff8111611acd5760051b60200190565b9080601f83011215610b2f576020908235611b9f81611b6d565b93611bad6040519586611b4b565b81855260208086019260051b820101928311610b2f57602001905b828210611bd6575050505090565b81358152908301908301611bc8565b67ffffffffffffffff8111611acd57601f01601f191660200190565b15611c0857565b60405162461bcd60e51b815260206004820152600a60248201526941646d696e206f6e6c7960b01b6044820152606490fd5b805115611c475760200190565b634e487b7160e01b600052603260045260246000fd5b91908203918211611c6a57565b634e487b7160e01b600052601160045260246000fd5b90816020910312610b2f57518015158103610b2f5790565b906002821015611ca55752565b634e487b7160e01b600052602160045260246000fd5b60005b838110611cce5750506000910152565b8181015183820152602001611cbe565b90602091611cf781518092818552858086019101611cbb565b601f01601f1916010190565b51906001600160a01b0382168203610b2f57565b9190604083820312610b2f57611d2c83611d03565b9260208101519067ffffffffffffffff8211610b2f570181601f82011215610b2f578051611d5981611be5565b92611d676040519485611b4b565b81845260208284010111610b2f57611d859160208085019101611cbb565b90565b9060409182519060c0820182811067ffffffffffffffff821117611acd5784526000602092818482015281868201528160608201528160808201528160a0820152809560018060a01b0380941691828152815190624d7b0960e81b825260049187818481885afa9081156120c257908791879161208a575b501690835163625048e960e11b815288818581895afa908115611fec579088918891612052575b501691737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9928382149384928395612034575b8315612001575b50505015611ff65750600160a08a0152825190630315311560e31b9283835286818401528683602481895afa928315611fec578793611fcf575b5084519380855260018286015287856024818a5afa948515611fc5578895611fa8575b508551968188526002838901528888602481845afa978815611f9e5790899392918499611f75575b5060039392916024918951958694859384528301525afa968715611f6a578097611f44575b505015611f2557908596868096979316908a01521690870152166060850152166080830152565b8516606089015284166080880152908316938601939093521690830152565b611f619297503d8091833e611f598183611b4b565b810190611d17565b50943880611efe565b8551903d90823e3d90fd5b602491995091611f9260039594933d8087833e611f598183611b4b565b50999150919293611ed9565b87513d8b823e3d90fd5b611fbd9195503d808a833e611f598183611b4b565b509338611eb1565b86513d8a823e3d90fd5b611fe49193503d8089833e611f598183611b4b565b509138611e8e565b85513d89823e3d90fd5b985050505050505050565b7340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f149250908261202a575b5050388080611e54565b1490503880612020565b7340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f83149350611e4d565b8092508a8092503d8311612083575b61206b8183611b4b565b810103126116d25761207d8891611d03565b38611e27565b503d612061565b809250898092503d83116120bb575b6120a38183611b4b565b8101031261044a576120b58791611d03565b38611e00565b503d612099565b84513d88823e3d90fd5b604051636eb1769f60e11b815230600482015273e592427a0aece92de3edee1f18e0157c05861564602482018190526020926001600160a01b0316918381604481865afa908115610a5857600091612178575b501561212a57505050565b60009160448492604051948593849263095ea7b360e01b84526004840152811960248401525af18015610a585761215f575050565b8161217592903d10610a8c57610a7d8183611b4b565b50565b90508381813d831161219e575b61218f8183611b4b565b81010312610b2f57513861211f565b503d612185565b604051636eb1769f60e11b815230600482015273ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc602482018190526020926001600160a01b0316918381604481865afa908115610a585760009161217857501561212a57505050565b6020815260a0608061221f845183602086015260c0850190611cde565b93600180841b03602082015116604085015260408101516060850152606081015182850152015191015290565b60405191610100830183811067ffffffffffffffff821117611acd5760405260018060a01b03809216835281602084019116815260408301936101f4855260608401903082526080850142815260a086019182528460c087019362ffffff6000998a87528360e08b01988c8a52816040519c8d63414bf38960e01b9052511660048d0152511660248b015251166044890152511660648701525160848601525160a48501525160c4840152511660e4820152602081610104818573e592427a0aece92de3edee1f18e0157c058615645af191821561236057809261232f57505090565b9091506020823d602011612358575b8161234b60209383611b4b565b810103126100ff57505190565b3d915061233e565b604051903d90823e3d90fdfe4b54c93455029207f8ce840d6befb957a3870db6da235d576946ab60d46134d6a2646970667358221220f9eb65a540b778f71e5cd5a6cde6fa2487656c8f6c0ec31363e88f334da4c72364736f6c63430008180033
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c8063069c9fae146119f15780630db188b1146119c2578063158274a5146119935780633add5c051461197657806348ccda3c1461194757806363075eb91461192a57806375829def146118a857806379dc9b321461188c57806389a302711461185d578063ad5c46481461182e578063b8d008f3146117ff578063c31c9c07146117d0578063ca216247146117b3578063f04f270714610464578063f3df2206146101025763f851a440146100d7575061000e565b346100ff57806003193601126100ff576001546040516001600160a01b039091168152602090f35b80fd5b50346100ff5760803660031901126100ff5761011c611a9b565b90604435602435600282101561046057606435906040519261013d84611b13565b84845284602085015284604085015284606080950152600285541461044e57600285555a60405190966001600160a01b03169190829061017d8184611c98565b8460208201527f6d46a9b7d1eee35a4a05f88046aeab446fa24dc8498c02f6c70f4bbfd684910e60403392a383604080516101b781611ab1565b8481528360208201520152816002549160ff60a01b9060a01b16916affffffffffffffffffffff60a81b1617178060025583600355336bffffffffffffffffffffffff60a01b60045416176004556040519361021285611b2f565b6001855261027d60208601926020368537737fc66500c84a76ad7e9c93437bfc5ac33e2ddae961024188611c3a565b526040519561024f87611b2f565b600187526020368189013761026387611c3a565b5260405194602086015260ff604086019160a01c16611c98565b8583015284825261028d82611b13565b73ba12222222228d8ba445958a75a0704d566bf2c83b1561044a57604051632e1c224f60e11b815230600482015260806024820152935160848501819052869385939092909160a485019190865b8181106104255750505060031984820301604485015260208084519283815201930190855b81811061040957505050828203600319016064840152829161032191611cde565b03818373ba12222222228d8ba445958a75a0704d566bf2c85af180156103fe576103e6575b506080926040519261035784611b13565b60ff6005541615158452600654602085019081526001600754926040870193845261038c600854958789019687525a90611c5d565b8086528351908551604051928352602083015260408201527f9348050869e3b84bcf0cf6e185f0f61f5b26d21989f1160a65a95bf52090db39873392a2556040519451151585525160208501525160408401525190820152f35b6103f08391611aff565b6103fa5738610346565b5080fd5b6040513d85823e3d90fd5b8251855289965087955060209485019490920191600101610300565b82516001600160a01b031684528a9750889650602093840193909201916001016102db565b8580fd5b604051633ee5aeb560e01b8152600490fd5b8280fd5b50346100ff5760803660031901126100ff5767ffffffffffffffff600435818111610460573660238201121561046057806004013590602460206104a784611b6d565b6104b46040519182611b4b565b848152019260051b82010190368211610e2857602401915b81831061179357505050602435818111610460576104ee903690600401611b85565b9060443581811161178f57610507903690600401611b85565b9160643591821161178f573660238301121561178f578160040135918461052d84611be5565b9161053b6040519384611b4b565b84835260208301943660248284010111610460578060246020930187378301015273ba12222222228d8ba445958a75a0704d566bf2c8330361175457606081805181010312610e28576040519261059184611ab1565b516001600160a01b038116810361044a578352604081015191600283101561044a5760606105ce926105d594602087015201516040850152611c3a565b5192611c3a565b5182018083116117405781516105f3906001600160a01b0316611d88565b60a08101511561171c576020810151610614906001600160a01b03166120cc565b604081015161062b906001600160a01b03166120cc565b6060810151610642906001600160a01b03166120cc565b6080810151610659906001600160a01b03166120cc565b6020810151610670906001600160a01b03166121a5565b6040810151610687906001600160a01b03166121a5565b606081015161069e906001600160a01b03166121a5565b60808101516106b5906001600160a01b03166121a5565b602083015160028110156117085761104b57805185906001600160a01b031673ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b156103fa57604051906301abf04560e71b82526004820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9602482015285604482015281816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af18015610e2c57611037575b50507f0d25117aca3bb15ab1bf182fe0905dfe8cb4185e0009febe06820439b337c98460408051737fc66500c84a76ad7e9c93437bfc5ac33e2ddae98152866020820152a16020818101516040516370a0823160e01b81523060048201529190829060249082906001600160a01b03165afa908115610a93578691611005575b5080610f6f575b5060408181015190516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa908115610a93578691610f3d575b5080610ea9575b5060608101516040516370a0823160e01b81523060048201528691602090829060249082906001600160a01b03165afa908115610e2c578291610e74575b5060808301516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103fe578391610e3f575b5080821015610e375750915b82610d46575b50506040516370a0823160e01b815230600482015290506020816024817340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f5afa908115610d3b578591610d09575b5080610b3c575b505b6040516370a0823160e01b8152306004820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae99190602081602481865afa908115610a93578691610b05575b50818110610abc5761094282604092611c5d565b930151808410610a9e575060405163a9059cbb60e01b9182825273ba12222222228d8ba445958a75a0704d566bf2c86004830152602482015260208160448189875af18015610a9357610a64575b50826109d4575b50508260606040516109a881611b13565b600181528360208201528460408201520152600160ff1960055416176005556006556007558060085580f35b60045460405160208082019384526001600160a01b039092166024820152604481018590529091600091610a1581606481015b03601f198101835282611b4b565b519082855af115610a58576000513d610a4f5750803b155b610a375780610997565b60249060405190635274afe760e01b82526004820152fd5b60011415610a2d565b6040513d6000823e3d90fd5b610a859060203d602011610a8c575b610a7d8183611b4b565b810190611c80565b5038610990565b503d610a73565b6040513d88823e3d90fd5b8360449160405191632744211560e11b835260048301526024820152fd5b60a49160405191633566cf0d60e01b835260048301526024820152606060448201526015606482015274496e73756666696369656e7420746f20726570617960581b6084820152fd5b90506020813d602011610b34575b81610b2060209383611b4b565b81010312610b2f57513861092e565b600080fd5b3d9150610b13565b6040517340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f60601b602082810191909152601960ea1b60348301527314170d3238c43166d83a33a945d3d619c6c0dd6960631b6037830152607d60ea1b604b830152736015551cd911ff4685072e2793f56c841e3ab66160611b604e83015261017760eb1b6062830152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae960601b606583015260598252610c2791610be781611b13565b60405190610bf482611ae3565b815230828201524260408201528360608201528760808201526040518093819263c04b8d5960e01b835260048301612202565b03818973e592427a0aece92de3edee1f18e0157c058615645af1908115610a93578691610cc9575b5060008051602061236d8339815191529160e0916040519160a08352600960a08401526847484f2d3e4141564560b81b60c08401527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6020840152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9604084015260608301526080820152a1386108eb565b90506020813d602011610d01575b81610ce460209383611b4b565b81010312610b2f575160008051602061236d833981519152610c4f565b3d9150610cd7565b90506020813d602011610d33575b81610d2460209383611b4b565b81010312610b2f5751386108e4565b3d9150610d17565b6040513d87823e3d90fd5b516001600160a01b031673ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b156103fa5760405190637abef8d160e01b825260048201527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f602482015282604482015281816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af18015610e2c57610e14575b505060407ff5bce2baecfbac717c0870301a2421776917796f559e40b2879651e7b88cf300918151907340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f82526020820152a13884816108a2565b610e1d90611aff565b610e28578438610dc6565b8480fd5b6040513d84823e3d90fd5b90509161089c565b9250506020823d602011610e6c575b81610e5b60209383611b4b565b81010312610b2f5786915138610890565b3d9150610e4e565b9150506020813d602011610ea1575b81610e9060209383611b4b565b81010312610b2f5785905138610853565b3d9150610e83565b6040820151608083015160008051602061236d8339815191529260e0929091610ee09183916001600160a01b03908116911661224c565b60018060a01b036040860151169160018060a01b036080870151166040519360a08552600f60a08601526e4e4f5f414156452d3e4e4f5f47484f60881b60c08601526020850152604084015260608301526080820152a138610815565b90506020813d602011610f67575b81610f5860209383611b4b565b81010312610b2f57513861080e565b3d9150610f4b565b6020820151606083015160008051602061236d8339815191529260e0929091610fa69183916001600160a01b03908116911661224c565b60018060a01b036020860151169160018060a01b036060870151166040519360a08552601160a0860152705945535f414156452d3e5945535f47484f60781b60c08601526020850152604084015260608301526080820152a1386107d1565b90506020813d60201161102f575b8161102060209383611b4b565b81010312610b2f5751386107ca565b3d9150611013565b61104090611aff565b610e2857843861074a565b604051737fc66500c84a76ad7e9c93437bfc5ac33e2ddae960601b60208281019190915261017760eb1b6034830152736015551cd911ff4685072e2793f56c841e3ab66160611b6037830152607d60ea1b604b8301527314170d3238c43166d83a33a945d3d619c6c0dd6960631b604e830152601960ea1b60628301527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f60601b606583015260598252611136916110f681611b13565b6040519061110382611ae3565b815230828201524260408201528660608201528760808201526040518093819263c04b8d5960e01b835260048301612202565b03818973e592427a0aece92de3edee1f18e0157c058615645af1908115610a935786916116d6575b5060008051602061236d83398151915260e060405160a08152600960a082015268414156452d3e47484f60b81b60c0820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae960208201527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6040820152876060820152836080820152a181516001600160a01b031673ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b156116d257604051906301abf04560e71b825260048201527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f602482015281604482015286816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af180156116c757611691575b5060407f0d25117aca3bb15ab1bf182fe0905dfe8cb4185e0009febe06820439b337c984918151907340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f82526020820152a160608101516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa908115610a9357869161165f575b50806115c9575b5060808101516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa908115610a93578691611597575b5080611507575b506020818101516040516370a0823160e01b815230600482015287929091829060249082906001600160a01b03165afa908115610e2c5782916114d2575b5060408381015190516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103fe57839161149d575b50808210156114955750915b826113b3575b5050506108ed565b516001600160a01b031673ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b156103fa5760405190637abef8d160e01b82526004820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9602482015282604482015281816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af18015610e2c57611481575b505060407ff5bce2baecfbac717c0870301a2421776917796f559e40b2879651e7b88cf30091815190737fc66500c84a76ad7e9c93437bfc5ac33e2ddae982526020820152a13884816113ab565b61148a90611aff565b610e28578438611433565b9050916113a5565b9250506020823d6020116114ca575b816114b960209383611b4b565b81010312610b2f5786915138611399565b3d91506114ac565b9150506020813d6020116114ff575b816114ee60209383611b4b565b81010312610b2f578590513861135c565b3d91506114e1565b6080820151604083015160008051602061236d8339815191529260e092909161153e9183916001600160a01b03908116911661224c565b608085810151604080880151815160a0808252600f908201526e4e4f5f47484f2d3e4e4f5f4141564560881b60c08201526001600160a01b0393841660208201529216908201526060810193909352820152a13861131e565b90506020813d6020116115c1575b816115b260209383611b4b565b81010312610b2f575138611317565b3d91506115a5565b6060820151602083015160008051602061236d8339815191529260e09290916116009183916001600160a01b03908116911661224c565b60018060a01b036060860151169160018060a01b036020870151166040519360a08552601160a0860152705945535f47484f2d3e5945535f4141564560781b60c08601526020850152604084015260608301526080820152a1386112da565b90506020813d602011611689575b8161167a60209383611b4b565b81010312610b2f5751386112d3565b3d915061166d565b7f0d25117aca3bb15ab1bf182fe0905dfe8cb4185e0009febe06820439b337c98491966116bf604092611aff565b969150611252565b6040513d89823e3d90fd5b8680fd5b90506020813d602011611700575b816116f160209383611b4b565b8101031261044a57513861115e565b3d91506116e4565b634e487b7160e01b86526021600452602486fd5b8251604051630aa7327760e31b81526001600160a01b039091166004820152602490fd5b634e487b7160e01b84526011600452602484fd5b60405162461bcd60e51b815260206004820152601360248201527213db9b1e4810985b185b98d95c8815985d5b1d606a1b6044820152606490fd5b8380fd5b82356001600160a01b038116810361044a578152602092830192016104cc565b50346100ff57806003193601126100ff576020604051610bb88152f35b50346100ff57806003193601126100ff57602060405173e592427a0aece92de3edee1f18e0157c058615648152f35b50346100ff57806003193601126100ff5760206040517340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f8152f35b50346100ff57806003193601126100ff57602060405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28152f35b50346100ff57806003193601126100ff57602060405173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488152f35b50346100ff57806003193601126100ff57602060405160648152f35b50346100ff5760203660031901126100ff576118c2611a9b565b600154906001600160a01b03906118dc3383851614611c01565b169081156118f5576001600160a01b0319161760015580f35b60405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21030b236b4b760991b6044820152606490fd5b50346100ff57806003193601126100ff5760206040516127108152f35b50346100ff57806003193601126100ff576020604051737fc66500c84a76ad7e9c93437bfc5ac33e2ddae98152f35b50346100ff57806003193601126100ff5760206040516101f48152f35b50346100ff57806003193601126100ff57602060405173ba12222222228d8ba445958a75a0704d566bf2c88152f35b50346100ff57806003193601126100ff57602060405173ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc8152f35b50346100ff5760403660031901126100ff57611a0b611a9b565b6001546001600160a01b03908116916020918491611a2a338614611c01565b60405163a9059cbb60e01b8582019081526001600160a01b0390961660248083019190915235604482015291169390611a668160648101610a07565b519082855af115611a8e5781513d611a855750803b155b610a37575080f35b60011415611a7d565b50604051903d90823e3d90fd5b600435906001600160a01b0382168203610b2f57565b6060810190811067ffffffffffffffff821117611acd57604052565b634e487b7160e01b600052604160045260246000fd5b60a0810190811067ffffffffffffffff821117611acd57604052565b67ffffffffffffffff8111611acd57604052565b6080810190811067ffffffffffffffff821117611acd57604052565b6040810190811067ffffffffffffffff821117611acd57604052565b90601f8019910116810190811067ffffffffffffffff821117611acd57604052565b67ffffffffffffffff8111611acd5760051b60200190565b9080601f83011215610b2f576020908235611b9f81611b6d565b93611bad6040519586611b4b565b81855260208086019260051b820101928311610b2f57602001905b828210611bd6575050505090565b81358152908301908301611bc8565b67ffffffffffffffff8111611acd57601f01601f191660200190565b15611c0857565b60405162461bcd60e51b815260206004820152600a60248201526941646d696e206f6e6c7960b01b6044820152606490fd5b805115611c475760200190565b634e487b7160e01b600052603260045260246000fd5b91908203918211611c6a57565b634e487b7160e01b600052601160045260246000fd5b90816020910312610b2f57518015158103610b2f5790565b906002821015611ca55752565b634e487b7160e01b600052602160045260246000fd5b60005b838110611cce5750506000910152565b8181015183820152602001611cbe565b90602091611cf781518092818552858086019101611cbb565b601f01601f1916010190565b51906001600160a01b0382168203610b2f57565b9190604083820312610b2f57611d2c83611d03565b9260208101519067ffffffffffffffff8211610b2f570181601f82011215610b2f578051611d5981611be5565b92611d676040519485611b4b565b81845260208284010111610b2f57611d859160208085019101611cbb565b90565b9060409182519060c0820182811067ffffffffffffffff821117611acd5784526000602092818482015281868201528160608201528160808201528160a0820152809560018060a01b0380941691828152815190624d7b0960e81b825260049187818481885afa9081156120c257908791879161208a575b501690835163625048e960e11b815288818581895afa908115611fec579088918891612052575b501691737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9928382149384928395612034575b8315612001575b50505015611ff65750600160a08a0152825190630315311560e31b9283835286818401528683602481895afa928315611fec578793611fcf575b5084519380855260018286015287856024818a5afa948515611fc5578895611fa8575b508551968188526002838901528888602481845afa978815611f9e5790899392918499611f75575b5060039392916024918951958694859384528301525afa968715611f6a578097611f44575b505015611f2557908596868096979316908a01521690870152166060850152166080830152565b8516606089015284166080880152908316938601939093521690830152565b611f619297503d8091833e611f598183611b4b565b810190611d17565b50943880611efe565b8551903d90823e3d90fd5b602491995091611f9260039594933d8087833e611f598183611b4b565b50999150919293611ed9565b87513d8b823e3d90fd5b611fbd9195503d808a833e611f598183611b4b565b509338611eb1565b86513d8a823e3d90fd5b611fe49193503d8089833e611f598183611b4b565b509138611e8e565b85513d89823e3d90fd5b985050505050505050565b7340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f149250908261202a575b5050388080611e54565b1490503880612020565b7340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f83149350611e4d565b8092508a8092503d8311612083575b61206b8183611b4b565b810103126116d25761207d8891611d03565b38611e27565b503d612061565b809250898092503d83116120bb575b6120a38183611b4b565b8101031261044a576120b58791611d03565b38611e00565b503d612099565b84513d88823e3d90fd5b604051636eb1769f60e11b815230600482015273e592427a0aece92de3edee1f18e0157c05861564602482018190526020926001600160a01b0316918381604481865afa908115610a5857600091612178575b501561212a57505050565b60009160448492604051948593849263095ea7b360e01b84526004840152811960248401525af18015610a585761215f575050565b8161217592903d10610a8c57610a7d8183611b4b565b50565b90508381813d831161219e575b61218f8183611b4b565b81010312610b2f57513861211f565b503d612185565b604051636eb1769f60e11b815230600482015273ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc602482018190526020926001600160a01b0316918381604481865afa908115610a585760009161217857501561212a57505050565b6020815260a0608061221f845183602086015260c0850190611cde565b93600180841b03602082015116604085015260408101516060850152606081015182850152015191015290565b60405191610100830183811067ffffffffffffffff821117611acd5760405260018060a01b03809216835281602084019116815260408301936101f4855260608401903082526080850142815260a086019182528460c087019362ffffff6000998a87528360e08b01988c8a52816040519c8d63414bf38960e01b9052511660048d0152511660248b015251166044890152511660648701525160848601525160a48501525160c4840152511660e4820152602081610104818573e592427a0aece92de3edee1f18e0157c058615645af191821561236057809261232f57505090565b9091506020823d602011612358575b8161234b60209383611b4b565b810103126100ff57505190565b3d915061233e565b604051903d90823e3d90fdfe4b54c93455029207f8ce840d6befb957a3870db6da235d576946ab60d46134d6a2646970667358221220f9eb65a540b778f71e5cd5a6cde6fa2487656c8f6c0ec31363e88f334da4c72364736f6c63430008180033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.