Source Code
Latest 1 from a total of 1 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Execute Arbitrag... | 24355025 | 29 days ago | IN | 0 ETH | 0.00011622 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AaveFlashArbitrageV6
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 V6 - DYNAMIC & UNIVERSAL ROUTER
// =============================================================================
//
// Features:
// 1. Dynamic Proposal Loading (not hardcoded)
// 2. Universal Router + Permit2 (V5 architecture)
// 3. Correct 0.05% Fee Tier for USDC/GHO (V6 fix)
// 4. Dynamic Token Approvals (safe & gas optimized)
// =============================================================================
// =============================================================================
// INTERFACES
// =============================================================================
interface IBalancerV2Vault {
function flashLoan(
address recipient,
IERC20[] memory tokens,
uint256[] memory amounts,
bytes memory userData
) external;
}
interface IUniversalRouter {
function execute(bytes calldata commands, bytes[] calldata inputs, uint256 deadline) external payable;
}
interface IPermit2 {
function approve(address token, address spender, uint160 amount, uint48 expiration) external;
function allowance(address user, address token, address spender) external view returns (uint160 amount, uint48 expiration, uint48 nonce);
}
interface IFutarchyRouter {
function splitPosition(address proposal, address collateralToken, uint256 amount) external;
function mergePositions(address proposal, address collateralToken, uint256 amount) external;
function proposals(address proposal) external view returns (address, address, uint256, uint256, address);
function wrappedOutcome(address proposal, address collateralToken) external view returns (address);
}
interface IFutarchyProposal {
function collateralToken1() external view returns (address);
function collateralToken2() external view returns (address);
function wrappedOutcome(uint256 index) external view returns (IERC20, bytes memory);
}
// =============================================================================
// CONTRACT
// =============================================================================
contract AaveFlashArbitrageV6 is ReentrancyGuard {
using SafeERC20 for IERC20;
// ==========================================================================
// CONSTANTS (Verified Mainnet Addresses)
// ==========================================================================
// Collateral tokens
address public constant AAVE = 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9;
address public constant GHO = 0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f;
address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
// Infrastructure
IBalancerV2Vault public constant balancerVault = IBalancerV2Vault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
IPermit2 public constant permit2 = IPermit2(0x000000000022D473030F116dDEE9F6B43aC78BA3);
IUniversalRouter public constant universalRouter = IUniversalRouter(0x66a9893cC07D91D95644AEDD05D03f95e1dBA8Af);
IFutarchyRouter public constant futarchyRouter = IFutarchyRouter(0xAc9Bf8EbA6Bd31f8E8c76f8E8B2AAd0BD93f98Dc);
// Fee tiers
uint24 public constant OUTCOME_FEE = 500; // 0.05% for outcome pools
uint24 public constant GHO_USDC_FEE = 500; // 0.05% for GHO/USDC (Fixed in V6!)
uint24 public constant USDC_WETH_FEE = 500; // 0.05% for USDC/WETH
uint24 public constant WETH_AAVE_FEE = 3000; // 0.3% for WETH/AAVE
// Constants
bytes1 public constant V3_SWAP_EXACT_IN = 0x00;
uint160 private constant MAX_UINT160 = type(uint160).max;
uint48 private constant MAX_UINT48 = type(uint48).max;
address public admin;
// ==========================================================================
// STRUCTS
// ==========================================================================
enum ArbitrageDirection { SPOT_SPLIT, MERGE_SPOT }
struct ArbitrageParams {
address proposal;
ArbitrageDirection direction;
uint256 minProfit;
}
struct ProposalInfo {
address proposal;
address yesAave;
address noAave;
address yesGho;
address noGho;
}
struct ArbitrageResult {
bool success;
uint256 profit;
uint256 borrowAmount;
uint256 gasUsed;
}
// Transient state
ArbitrageParams private _params;
address private _profitRecipient;
ArbitrageResult private _lastResult;
// ==========================================================================
// EVENTS & ERRORS
// ==========================================================================
event ArbitrageExecuted(
address indexed caller,
address indexed proposal,
ArbitrageDirection direction,
uint256 borrowAmount,
uint256 profit,
uint256 gasUsed
);
error ArbitrageFailed(uint256 balanceAfter, uint256 required, string reason);
error InvalidProposal(address proposal);
// ==========================================================================
// CONSTRUCTOR
// ==========================================================================
constructor() {
admin = msg.sender;
// 1. Approve Static Tokens to Permit2
IERC20(AAVE).approve(address(permit2), type(uint256).max);
IERC20(GHO).approve(address(permit2), type(uint256).max);
IERC20(USDC).approve(address(permit2), type(uint256).max);
IERC20(WETH).approve(address(permit2), type(uint256).max);
// 2. Approve Permit2 -> Universal Router for Static Tokens
permit2.approve(AAVE, address(universalRouter), MAX_UINT160, MAX_UINT48);
permit2.approve(GHO, address(universalRouter), MAX_UINT160, MAX_UINT48);
permit2.approve(USDC, address(universalRouter), MAX_UINT160, MAX_UINT48);
permit2.approve(WETH, address(universalRouter), MAX_UINT160, MAX_UINT48);
// 3. Approve Static Tokens to FutarchyRouter
IERC20(AAVE).approve(address(futarchyRouter), type(uint256).max);
IERC20(GHO).approve(address(futarchyRouter), type(uint256).max);
}
// ==========================================================================
// EXTERNAL: EXECUTE ARBITRAGE
// ==========================================================================
function executeArbitrage(
address proposalAddress,
uint256 borrowAmount,
ArbitrageDirection direction,
uint256 minProfit
) external nonReentrant returns (ArbitrageResult memory result) {
uint256 gasStart = gasleft();
_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 ArbitrageExecuted(msg.sender, proposalAddress, direction, borrowAmount, result.profit, 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];
// 1. Load Proposal Tokens
ProposalInfo memory info = _loadProposal(params.proposal);
// 2. Setup Dynamic Approvals
_setupOutcomeApprovals(info);
// 3. Execute Strategy
if (params.direction == ArbitrageDirection.SPOT_SPLIT) {
_executeSpotSplit(info, borrowAmount);
} else {
_executeMergeSpot(info, borrowAmount);
}
// 4. Verify & Repay
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 ArbitrageFailed(aaveBalance, repayAmount, "Profit below minimum");
}
IERC20(AAVE).transfer(address(balancerVault), repayAmount);
if (profit > 0) {
IERC20(AAVE).safeTransfer(_profitRecipient, profit);
}
_lastResult = ArbitrageResult({
success: true,
profit: profit,
borrowAmount: borrowAmount,
gasUsed: 0
});
}
// ==========================================================================
// DYNAMIC LOADING & APPROVALS
// ==========================================================================
function _loadProposal(address proposalAddress) internal view returns (ProposalInfo memory info) {
IFutarchyProposal proposal = IFutarchyProposal(proposalAddress);
info.proposal = proposalAddress;
address col1 = proposal.collateralToken1();
address col2 = proposal.collateralToken2();
// AAVE Outcomes
if (col1 == AAVE) {
(IERC20 yes, ) = proposal.wrappedOutcome(0);
(IERC20 no, ) = proposal.wrappedOutcome(1);
info.yesAave = address(yes);
info.noAave = address(no);
} else if (col2 == AAVE) {
(IERC20 yes, ) = proposal.wrappedOutcome(2);
(IERC20 no, ) = proposal.wrappedOutcome(3);
info.yesAave = address(yes);
info.noAave = address(no);
} else {
revert("AAVE not collateral");
}
// GHO Outcomes
if (col1 == GHO) {
(IERC20 yes, ) = proposal.wrappedOutcome(0);
(IERC20 no, ) = proposal.wrappedOutcome(1);
info.yesGho = address(yes);
info.noGho = address(no);
} else if (col2 == GHO) {
(IERC20 yes, ) = proposal.wrappedOutcome(2);
(IERC20 no, ) = proposal.wrappedOutcome(3);
info.yesGho = address(yes);
info.noGho = address(no);
} else {
revert("GHO not collateral");
}
}
function _setupOutcomeApprovals(ProposalInfo memory info) internal {
_approveIfNecessary(info.yesAave);
_approveIfNecessary(info.noAave);
_approveIfNecessary(info.yesGho);
_approveIfNecessary(info.noGho);
}
function _approveIfNecessary(address token) internal {
// 1. Approve to Permit2
if (IERC20(token).allowance(address(this), address(permit2)) == 0) {
IERC20(token).approve(address(permit2), type(uint256).max);
}
// 2. Approve Permit2 -> Universal Router (Requires Permit2 call)
(uint160 amount, , ) = permit2.allowance(address(this), token, address(universalRouter));
if (amount == 0) {
permit2.approve(token, address(universalRouter), MAX_UINT160, MAX_UINT48);
}
// 3. Approve to FutarchyRouter
if (IERC20(token).allowance(address(this), address(futarchyRouter)) == 0) {
IERC20(token).approve(address(futarchyRouter), type(uint256).max);
}
}
// ==========================================================================
// STRATEGIES
// ==========================================================================
function _executeSpotSplit(ProposalInfo memory info, uint256 amount) internal {
// 1. Split AAVE -> YES_AAVE + NO_AAVE
futarchyRouter.splitPosition(info.proposal, AAVE, amount);
// 2. Swap YES_AAVE -> YES_GHO
uint256 yesAaveBal = IERC20(info.yesAave).balanceOf(address(this));
if (yesAaveBal > 0) {
_swap(info.yesAave, info.yesGho, OUTCOME_FEE, yesAaveBal);
}
// 3. Swap NO_AAVE -> NO_GHO
uint256 noAaveBal = IERC20(info.noAave).balanceOf(address(this));
if (noAaveBal > 0) {
_swap(info.noAave, info.noGho, OUTCOME_FEE, noAaveBal);
}
// 4. Merge YES_GHO + NO_GHO -> GHO
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);
}
// 5. Swap GHO -> AAVE (multi-hop via USDC -> WETH)
uint256 ghoBal = IERC20(GHO).balanceOf(address(this));
if (ghoBal > 0) {
_swapGhoToAave(ghoBal);
}
}
function _executeMergeSpot(ProposalInfo memory info, uint256 amount) internal {
// 1. Swap AAVE -> GHO
_swapAaveToGho(amount);
uint256 ghoBal = IERC20(GHO).balanceOf(address(this));
// 2. Split GHO -> YES_GHO + NO_GHO
futarchyRouter.splitPosition(info.proposal, GHO, ghoBal);
// 3. Swap YES_GHO -> YES_AAVE
uint256 yesGhoBal = IERC20(info.yesGho).balanceOf(address(this));
if (yesGhoBal > 0) {
_swap(info.yesGho, info.yesAave, OUTCOME_FEE, yesGhoBal);
}
// 4. Swap NO_GHO -> NO_AAVE
uint256 noGhoBal = IERC20(info.noGho).balanceOf(address(this));
if (noGhoBal > 0) {
_swap(info.noGho, info.noAave, OUTCOME_FEE, noGhoBal);
}
// 5. Merge YES_AAVE + NO_AAVE -> AAVE
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);
}
}
// ==========================================================================
// SWAP HELPERS
// ==========================================================================
function _swap(address tokenIn, address tokenOut, uint24 fee, uint256 amountIn) internal {
bytes memory path = abi.encodePacked(tokenIn, fee, tokenOut);
bytes memory swapParams = abi.encode(
address(this),
amountIn,
0,
path,
true // payerIsUser (Permit2 pull)
);
bytes memory commands = abi.encodePacked(V3_SWAP_EXACT_IN);
bytes[] memory inputs = new bytes[](1);
inputs[0] = swapParams;
universalRouter.execute(commands, inputs, block.timestamp);
}
function _swapGhoToAave(uint256 amountIn) internal {
// GHO -> USDC (0.05%!) -> WETH (0.05%) -> AAVE (0.3%)
bytes memory path = abi.encodePacked(
GHO, GHO_USDC_FEE, // 500
USDC, USDC_WETH_FEE, // 500
WETH, WETH_AAVE_FEE, // 3000
AAVE
);
bytes memory swapParams = abi.encode(
address(this),
amountIn,
0,
path,
true
);
bytes memory commands = abi.encodePacked(V3_SWAP_EXACT_IN);
bytes[] memory inputs = new bytes[](1);
inputs[0] = swapParams;
universalRouter.execute(commands, inputs, block.timestamp);
}
function _swapAaveToGho(uint256 amountIn) internal {
// AAVE -> WETH (0.3%) -> USDC (0.05%) -> GHO (0.05%!)
bytes memory path = abi.encodePacked(
AAVE, WETH_AAVE_FEE, // 3000
WETH, USDC_WETH_FEE, // 500
USDC, GHO_USDC_FEE, // 500
GHO
);
bytes memory swapParams = abi.encode(
address(this),
amountIn,
0,
path,
true
);
bytes memory commands = abi.encodePacked(V3_SWAP_EXACT_IN);
bytes[] memory inputs = new bytes[](1);
inputs[0] = swapParams;
universalRouter.execute(commands, inputs, block.timestamp);
}
// ==========================================================================
// ADMIN
// ==========================================================================
function recoverTokens(address token, uint256 amount) external {
require(msg.sender == admin, "Admin only");
IERC20(token).safeTransfer(admin, amount);
}
}// 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":"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":true,"internalType":"address","name":"proposal","type":"address"},{"indexed":false,"internalType":"enum AaveFlashArbitrageV6.ArbitrageDirection","name":"direction","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"profit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"}],"name":"ArbitrageExecuted","type":"event"},{"inputs":[],"name":"AAVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GHO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GHO_USDC_FEE","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OUTCOME_FEE","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC_WETH_FEE","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"V3_SWAP_EXACT_IN","outputs":[{"internalType":"bytes1","name":"","type":"bytes1"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH_AAVE_FEE","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"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 AaveFlashArbitrageV6.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 AaveFlashArbitrageV6.ArbitrageResult","name":"result","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"futarchyRouter","outputs":[{"internalType":"contract IFutarchyRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permit2","outputs":[{"internalType":"contract IPermit2","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":"universalRouter","outputs":[{"internalType":"contract IUniversalRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60808060405234620005f5576001600081815581546001600160a01b031916331790915563095ea7b360e01b82526e22d473030f116ddee9f6b43ac78ba3600483015260001960248301529060208160448185737fc66500c84a76ad7e9c93437bfc5ac33e2ddae95af18015620004fd57620005d1575b5060405163095ea7b360e01b81526e22d473030f116ddee9f6b43ac78ba360048201526000196024820152602081604481857340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f5af18015620004fd57620005ad575b5060405163095ea7b360e01b81526e22d473030f116ddee9f6b43ac78ba3600482015260001960248201526020816044818573a0b86991c6218b36c1d19d4a2e9eb0ce3606eb485af18015620004fd5762000589575b5060405163095ea7b360e01b81526e22d473030f116ddee9f6b43ac78ba3600482015260001960248201526020816044818573c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af18015620004fd5762000565575b506e22d473030f116ddee9f6b43ac78ba33b1562000520576040516387517c4560e01b8152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae960048201527366a9893cc07d91d95644aedd05d03f95e1dba8af60248201526001600160a01b03604482015265ffffffffffff60648201528181608481836e22d473030f116ddee9f6b43ac78ba35af18015620004fd5762000553575b506e22d473030f116ddee9f6b43ac78ba33b1562000520576040516387517c4560e01b81527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f60048201527366a9893cc07d91d95644aedd05d03f95e1dba8af60248201526001600160a01b03604482015265ffffffffffff606482015281908181608481836e22d473030f116ddee9f6b43ac78ba35af18015620004fd576200053b575b50506e22d473030f116ddee9f6b43ac78ba33b1562000520576040516387517c4560e01b815273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4860048201527366a9893cc07d91d95644aedd05d03f95e1dba8af60248201526001600160a01b03604482015265ffffffffffff606482015281908181608481836e22d473030f116ddee9f6b43ac78ba35af18015620004fd5762000523575b50506e22d473030f116ddee9f6b43ac78ba33b1562000520576040516387517c4560e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260048201527366a9893cc07d91d95644aedd05d03f95e1dba8af60248201526001600160a01b03604482015265ffffffffffff606482015281908181608481836e22d473030f116ddee9f6b43ac78ba35af18015620004fd5762000508575b505060405163095ea7b360e01b815273ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc600482018190526000196024830152919060208160448185737fc66500c84a76ad7e9c93437bfc5ac33e2ddae95af18015620004fd57620004d9575b5060405163095ea7b360e01b815260048101929092526000196024830152602082604481847340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f5af1908115620004cd575062000497575b6040516123dd9081620006638239f35b620004bd9060203d602011620004c5575b620004b4818362000624565b81019062000648565b503862000487565b503d620004a8565b604051903d90823e3d90fd5b620004f59060203d602011620004c557620004b4818362000624565b50386200043c565b6040513d84823e3d90fd5b6200051390620005fa565b62000520578038620003dc565b80fd5b6200052e90620005fa565b6200052057803862000342565b6200054690620005fa565b62000520578038620002a8565b6200055e90620005fa565b386200020f565b620005819060203d602011620004c557620004b4818362000624565b503862000178565b620005a59060203d602011620004c557620004b4818362000624565b503862000122565b620005c99060203d602011620004c557620004b4818362000624565b5038620000cc565b620005ed9060203d602011620004c557620004b4818362000624565b503862000076565b600080fd5b6001600160401b0381116200060e57604052565b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b038211908210176200060e57604052565b90816020910312620005f557518015158103620005f5579056fe608080604052600436101561001357600080fd5b6000803560e01c918263069c9fae14611b18575081630db188b114611aea57816312261ee714611ac1578163158274a514611a9357816335a9e4df14611a6557816337375cac14611a4a578163409c02ed14611a2e57816348ccda3c14611a0057816389a30271146119d2578163ad5c4648146119a4578163b43943d2146100dc578163b8d008f314611976578163f04f27071461044f578163f3df22061461010c578163f4e7592e146100dc578163f851a440146100e1575063f9dec1ce146100dc57600080fd5b611c0f565b346101095780600319360112610109576001546040516001600160a01b039091168152602090f35b80fd5b3461010957608036600319011261010957610125611bf9565b90600260443510156101095780606060405161014081611c70565b8281528260208201528260408201520152600281541461043d57600281555a60405161016b81611c2c565b6001600160a01b038416808252604435602083018190526064356040938401819052600280546001600160a81b03191690931760a09290921b60ff60a01b169190911791829055600355600480546001600160a01b031916331790559051906101d382611c8b565b6001825260208201906020368337737fc66500c84a76ad7e9c93437bfc5ac33e2ddae96101ff84611d6d565b526040519161020d83611c8b565b600183526020368185013760243561022484611d6d565b52604080516001600160a01b03891660208201529261024b9184019060a01c60ff16611dcb565b60643560608301526060825261026082611c70565b73ba12222222228d8ba445958a75a0704d566bf2c83b1561043957604051632e1c224f60e11b815230600482015260806024820152935160848501819052869385939092909160a485019190865b8181106104145750505060031984820301604485015260208084519283815201930190855b8181106103f85750505082820360031901606484015282916102f491611e11565b03818373ba12222222228d8ba445958a75a0704d566bf2c85af180156103ed576103d5575b506080926040519261032a84611c70565b60ff600554161515845260016006549160208601928352600754936040870194855261036160085496606089019788525a90611d90565b908187528451916040519261037884604435611dcb565b602435602085015260408401526060830152838060a01b0316907fdc5019d79074cd354a501d0301da4a3d55c05c601593f6e2da04de191ae9337c893392a355604051935115158452516020840152516040830152516060820152f35b6103df8391611c5d565b6103e95783610319565b5080fd5b6040513d85823e3d90fd5b82518552899650879550602094850194909201916001016102d3565b82516001600160a01b031684528a9750889650602093840193909201916001016102ae565b8580fd5b604051633ee5aeb560e01b8152600490fd5b34610109576080366003190112610109576004356001600160401b0381116103e957366023820112156103e9578060040135906024602061048f84611cc7565b61049c6040519182611ca6565b848152019260051b82010190368211610def57602401915b81831061195657836024356001600160401b0381116103e9576104db903690600401611cde565b6044356001600160401b038111610ecd576104fa903690600401611cde565b90606435906001600160401b038211610def5736602383011215610def578160040135918461052884611d3e565b916105366040519384611ca6565b84835260208301943660248284010111610ecd578060246020930187378301015273ba12222222228d8ba445958a75a0704d566bf2c8330361191b57606081805181010312611917576105946040519361058f85611c2c565b611d59565b835260408101519160028310156104395760606105c0926105c794602087015201516040850152611d6d565b5192611d6d565b518201808311611903578151604051906001600160a01b031660a082016001600160401b038111838210176118ef57604052856020830152856040830152856060830152856080830152808252604051624d7b0960e81b8152602081600481855afa9081156115b35787916118b1575b5060405163625048e960e11b815290602082600481865afa9182156118a6578892611866575b506001600160a01b038116737fc66500c84a76ad7e9c93437bfc5ac33e2ddae90361174457604051630315311560e31b815260048101899052908882602481875afa91821561173957899261171c575b50604051630315311560e31b815260016004820152918983602481885afa908115611711577340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f938b926116f4575b506001600160a01b0390811660208801521660408601525b6001600160a01b0316036115e85750604051630315311560e31b81526004810187905290868083602481855afa9182156115db5760249382936115be575b50604051630315311560e31b81526001600482015293849182905afa9182156115b357879261158e575b506001600160a01b0390811660608401521660808201525b602081015161079e906001600160a01b0316611ec2565b60408101516107b5906001600160a01b0316611ec2565b60608101516107cc906001600160a01b0316611ec2565b60808101516107e3906001600160a01b0316611ec2565b6020830151600281101561157a5785919061101a5780516001600160a01b031673ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b15610ecd57604051906301abf04560e71b82526004820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9602482015285604482015282816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af19081156103ed578391611006575b50506020818101516040516370a0823160e01b81523060048201529190829060249082906001600160a01b03165afa9081156103ed578391610fd1575b5080610faa575b5060408181015190516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103ed578391610f75575b5080610f4e575b5060608101516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103ed578391610f19575b5060808201516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa908115610f0e578491610ed9575b5080821015610ed15750905b81610e33575b50506040516370a0823160e01b81523060048201526020816024817340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f5afa908115610df3578291610dfe575b5080610c9e575b50505b6040516370a0823160e01b8152306004820152602081602481737fc66500c84a76ad7e9c93437bfc5ac33e2ddae95afa908115610bcb578591610c67575b50818110610c1e576040610a2c8383611d90565b9301518310610bd6575060405163a9059cbb60e01b9182825273ba12222222228d8ba445958a75a0704d566bf2c86004830152602482015260208160448188737fc66500c84a76ad7e9c93437bfc5ac33e2ddae95af18015610bcb57610b9c575b5081610ad0575b50826060604051610aa481611c70565b600181528360208201528460408201520152600160ff1960055416176005556006556007558060085580f35b60045460405160208082019384526001600160a01b039092166024820152604481018490529091600091610b1181606481015b03601f198101835282611ca6565b519082737fc66500c84a76ad7e9c93437bfc5ac33e2ddae95af115610b90576000513d610b875750737fc66500c84a76ad7e9c93437bfc5ac33e2ddae93b155b610b5b5783610a94565b604051635274afe760e01b8152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae96004820152602490fd5b60011415610b51565b6040513d6000823e3d90fd5b610bbd9060203d602011610bc4575b610bb58183611ca6565b810190611db3565b5084610a8d565b503d610bab565b6040513d87823e3d90fd5b60a49160405191633566cf0d60e01b83526004830152602482015260606044820152601460648201527350726f6669742062656c6f77206d696e696d756d60601b6084820152fd5b60a49160405191633566cf0d60e01b835260048301526024820152606060448201526015606482015274496e73756666696369656e7420746f20726570617960581b6084820152fd5b90506020813d602011610c96575b81610c8260209383611ca6565b81010312610c91575185610a18565b600080fd5b3d9150610c75565b6040517340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f60601b6020820152607d60ea1b603482018190527314170d3238c43166d83a33a945d3d619c6c0dd6960631b6037830152604b820152736015551cd911ff4685072e2793f56c841e3ab66160611b604e82015261017760eb1b6062820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae960601b60658201526059815290610d5690610d4383611c70565b610b0360405193849230602085016121b4565b6040519082602083015260018252610d6d82611c8b565b610d756121eb565b90610d7f82611d6d565b52610d8981611d6d565b507366a9893cc07d91d95644aedd05d03f95e1dba8af91823b15610def57610dcc92849283604051809681958294630d64d59360e21b8452429160048501612220565b03925af18015610df357156109d757610de490611c5d565b610def5783856109d7565b8380fd5b6040513d84823e3d90fd5b9150506020813d602011610e2b575b81610e1a60209383611ca6565b81010312610c9157849051866109d0565b3d9150610e0d565b516001600160a01b03169073ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b15610ecd5760405191637abef8d160e01b835260048301527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6024830152604482015281816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af18015610df357610eb9575b80610990565b610ec290611c5d565b610def578385610eb3565b8280fd5b90509061098a565b9350506020833d602011610f06575b81610ef560209383611ca6565b81010312610c91578692518861097e565b3d9150610ee8565b6040513d86823e3d90fd5b9250506020823d602011610f46575b81610f3560209383611ca6565b81010312610c915785915187610941565b3d9150610f28565b60408201516080830151610f6f92916001600160a01b03918216911661229d565b86610904565b9250506020823d602011610fa2575b81610f9160209383611ca6565b81010312610c9157859151876108fd565b3d9150610f84565b60208201516060830151610fcb92916001600160a01b03918216911661229d565b866108c0565b9250506020823d602011610ffe575b81610fed60209383611ca6565b81010312610c9157859151876108b9565b3d9150610fe0565b61100f90611c5d565b6103e957818761087c565b604051737fc66500c84a76ad7e9c93437bfc5ac33e2ddae960601b602082015261017760eb1b6034820152736015551cd911ff4685072e2793f56c841e3ab66160611b6037820152607d60ea1b604b82018190527314170d3238c43166d83a33a945d3d619c6c0dd6960631b604e83015260628201527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f60601b606582015260598152909150610b03906110d6906110c581611c70565b6040519283918830602085016121b4565b85604051816020820152600181526110ed81611c8b565b6110f56121eb565b926110ff84611d6d565b5261110983611d6d565b507366a9893cc07d91d95644aedd05d03f95e1dba8af3b156103e957604051630d64d59360e21b815292839182916111479142919060048501612220565b0381837366a9893cc07d91d95644aedd05d03f95e1dba8af5af1801561156f5761155c575b506040516370a0823160e01b81523060048201528591906020816024817340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f5afa9081156103ed578391611527575b5081516001600160a01b03169073ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b15610def57604051916301abf04560e71b835260048301527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6024830152604482015282816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af19081156103ed578391611513575b505060608101516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103ed5783916114de575b50806114b7575b5060808101516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103ed578391611482575b508061145b575b506020818101516040516370a0823160e01b81523060048201529190829060249082906001600160a01b03165afa9081156103ed578391611426575b5060408281015190516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa908115610f0e5784916113f1575b50808210156113e95750905b8161134f575b5050506109da565b516001600160a01b03169073ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b15610ecd5760405191637abef8d160e01b83526004830152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae96024830152604482015281816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af18015610df3576113d5575b80611347565b6113de90611c5d565b610def5783856113cf565b905090611341565b9350506020833d60201161141e575b8161140d60209383611ca6565b81010312610c915786925188611335565b3d9150611400565b9250506020823d602011611453575b8161144260209383611ca6565b81010312610c9157859151876112f8565b3d9150611435565b6080820151604083015161147c92916001600160a01b03918216911661229d565b866112bc565b9250506020823d6020116114af575b8161149e60209383611ca6565b81010312610c9157859151876112b5565b3d9150611491565b606082015160208301516114d892916001600160a01b03918216911661229d565b86611278565b9250506020823d60201161150b575b816114fa60209383611ca6565b81010312610c915785915187611271565b3d91506114ed565b61151c90611c5d565b6103e9578187611233565b9250506020823d602011611554575b8161154360209383611ca6565b81010312610c9157859151876111ae565b3d9150611536565b61156890959195611c5d565b938561116c565b6040513d88823e3d90fd5b634e487b7160e01b86526021600452602486fd5b6115ab9192503d8089833e6115a38183611ca6565b810190611e36565b50908761076f565b6040513d89823e3d90fd5b6115d39193503d8084833e6115a38183611ca6565b509189610745565b50604051903d90823e3d90fd5b6001600160a01b03167340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f036116ba57604051630315311560e31b81526002600482015290868083602481855afa9182156115db57602493829361169d575b50604051630315311560e31b81526003600482015293849182905afa9182156115b3578792611680575b506001600160a01b039081166060840152166080820152610787565b6116959192503d8089833e6115a38183611ca6565b509087611664565b6116b29193503d8084833e6115a38183611ca6565b50918961163a565b60405162461bcd60e51b815260206004820152601260248201527111d213c81b9bdd0818dbdb1b185d195c985b60721b6044820152606490fd5b6117099192503d808d833e6115a38183611ca6565b50908b6106ef565b6040513d8c823e3d90fd5b6117319192503d808b833e6115a38183611ca6565b5090896106ad565b6040513d8b823e3d90fd5b6001600160a01b038216737fc66500c84a76ad7e9c93437bfc5ac33e2ddae90361182b57604051630315311560e31b815260026004820152908882602481875afa91821561173957899261180e575b50604051630315311560e31b815260036004820152918983602481885afa908115611711577340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f938b926117f1575b506001600160a01b039081166020880152166040860152610707565b6118069192503d808d833e6115a38183611ca6565b50908b6117d5565b6118239192503d808b833e6115a38183611ca6565b509089611793565b60405162461bcd60e51b815260206004820152601360248201527210505591481b9bdd0818dbdb1b185d195c985b606a1b6044820152606490fd5b9091506020813d60201161189e575b8161188260209383611ca6565b8101031261189a5761189390611d59565b908861065d565b8780fd5b3d9150611875565b6040513d8a823e3d90fd5b90506020813d6020116118e7575b816118cc60209383611ca6565b810103126118e3576118dd90611d59565b87610637565b8680fd5b3d91506118bf565b634e487b7160e01b87526041600452602487fd5b634e487b7160e01b84526011600452602484fd5b8480fd5b60405162461bcd60e51b815260206004820152601360248201527213db9b1e4810985b185b98d95c8815985d5b1d606a1b6044820152606490fd5b82356001600160a01b0381168103611917578152602092830192016104b4565b3461010957806003193601126101095760206040517340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f8152f35b34610109578060031936011261010957602060405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28152f35b34610109578060031936011261010957602060405173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488152f35b346101095780600319360112610109576020604051737fc66500c84a76ad7e9c93437bfc5ac33e2ddae98152f35b346101095780600319360112610109576020604051610bb88152f35b34610109578060031936011261010957602090604051908152f35b3461010957806003193601126101095760206040517366a9893cc07d91d95644aedd05d03f95e1dba8af8152f35b34610109578060031936011261010957602060405173ba12222222228d8ba445958a75a0704d566bf2c88152f35b3461010957806003193601126101095760206040516e22d473030f116ddee9f6b43ac78ba38152f35b34610109578060031936011261010957602060405173ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc8152f35b346103e95760403660031901126103e957611b31611bf9565b60018060a01b0390816001541692833303611bca575060405163a9059cbb60e01b60208281019182526001600160a01b03909516602480840191909152356044830152919092169291849190611b8a8160648101610b03565b519082855af1156115db5781513d611bc15750803b155b611ba9575080f35b60249060405190635274afe760e01b82526004820152fd5b60011415611ba1565b62461bcd60e51b815260206004820152600a60248201526941646d696e206f6e6c7960b01b6044820152606490fd5b600435906001600160a01b0382168203610c9157565b34610c91576000366003190112610c915760206040516101f48152f35b606081019081106001600160401b03821117611c4757604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b038111611c4757604052565b608081019081106001600160401b03821117611c4757604052565b604081019081106001600160401b03821117611c4757604052565b90601f801991011681019081106001600160401b03821117611c4757604052565b6001600160401b038111611c475760051b60200190565b9080601f83011215610c91576020908235611cf881611cc7565b93611d066040519586611ca6565b81855260208086019260051b820101928311610c9157602001905b828210611d2f575050505090565b81358152908301908301611d21565b6001600160401b038111611c4757601f01601f191660200190565b51906001600160a01b0382168203610c9157565b805115611d7a5760200190565b634e487b7160e01b600052603260045260246000fd5b91908203918211611d9d57565b634e487b7160e01b600052601160045260246000fd5b90816020910312610c9157518015158103610c915790565b906002821015611dd85752565b634e487b7160e01b600052602160045260246000fd5b60005b838110611e015750506000910152565b8181015183820152602001611df1565b90602091611e2a81518092818552858086019101611dee565b601f01601f1916010190565b9190604083820312610c915782516001600160a01b0381168103610c9157926020810151906001600160401b038211610c91570181601f82011215610c91578051611e8081611d3e565b92611e8e6040519485611ca6565b81845260208284010111610c9157611eac9160208085019101611dee565b90565b519065ffffffffffff82168203610c9157565b60018060a01b0380911660408051636eb1769f60e11b9283825260049330858401526e22d473030f116ddee9f6b43ac78ba3602495818786015260209760449289878581895afa80156121a957600097889161217c575b5015612123575b87519063927da10560e01b82523084830152868a8301527366a9893cc07d91d95644aedd05d03f95e1dba8af918286820152606081606481855afa908115612119579084918a916120b8575b50161561205a575b5050508551928352308184015273ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc92838882015288818481885afa908115612050578691612023575b5015611fc2575b5050505050505050565b8488948751988995869463095ea7b360e01b8652850152600019908401525af1918215612019575050611ffb575b808080808080611fb8565b8161201192903d10610bc457610bb58183611ca6565b503880611ff0565b51903d90823e3d90fd5b90508881813d8311612049575b61203a8183611ca6565b81010312610c91575138611fb1565b503d612030565b87513d88823e3d90fd5b803b1561189a579060848a8980948c5196879586946387517c4560e01b86528d8b8701528501528984015265ffffffffffff60648401525af18015612050576120a5575b8080611f74565b6120b190959195611c5d565b933861209e565b9150506060813d606011612111575b816120d460609383611ca6565b8101031261210d57805190848216820361210957906121028b838f6120fb90899601611eaf565b5001611eaf565b5038611f6c565b8980fd5b8880fd5b3d91506120c7565b8a513d8b823e3d90fd5b875163095ea7b360e01b81528381018290526000198a8201528a8186818b8b5af1801561217257612155575b50611f20565b61216b908b3d8d11610bc457610bb58183611ca6565b503861214f565b89513d8a823e3d90fd5b90508a81813d83116121a2575b6121938183611ca6565b8101031261189a575138611f19565b503d612189565b88513d6000823e3d90fd5b93926121e690600193608093858060a01b0316875260208701526000604087015260a0606087015260a0860190611e11565b930152565b6040516121f781611c8b565b600181528060005b60208082101561221a579060606020928285010152016121ff565b50505090565b9392919061223690606086526060860190611e11565b906020858303818701528151908184528084019381808460051b8301019401946000915b84831061226f57505050505060409150930152565b9091929394848061228c600193601f198682030187528a51611e11565b98019301930191959493929061225a565b91612302919392604051946bffffffffffffffffffffffff19809260601b166020870152607d60ea1b603487015260601b166037850152602b84526122e184611c2c565b6122f460405194859230602085016121b4565b03601f198101845283611ca6565b604051916000908160208501526001845261231c84611c8b565b6123246121eb565b9061232e82611d6d565b5261233881611d6d565b507366a9893cc07d91d95644aedd05d03f95e1dba8af90813b15610ecd5793829161237d949583604051809781958294630d64d59360e21b8452429160048501612220565b03925af190811561239b57506123905750565b61239990611c5d565b565b604051903d90823e3d90fdfea26469706673582212208946ef5cc84f2cda70da7a86c22cab1163dd3f5e35b90f347955897c66c6b90364736f6c63430008180033
Deployed Bytecode
0x608080604052600436101561001357600080fd5b6000803560e01c918263069c9fae14611b18575081630db188b114611aea57816312261ee714611ac1578163158274a514611a9357816335a9e4df14611a6557816337375cac14611a4a578163409c02ed14611a2e57816348ccda3c14611a0057816389a30271146119d2578163ad5c4648146119a4578163b43943d2146100dc578163b8d008f314611976578163f04f27071461044f578163f3df22061461010c578163f4e7592e146100dc578163f851a440146100e1575063f9dec1ce146100dc57600080fd5b611c0f565b346101095780600319360112610109576001546040516001600160a01b039091168152602090f35b80fd5b3461010957608036600319011261010957610125611bf9565b90600260443510156101095780606060405161014081611c70565b8281528260208201528260408201520152600281541461043d57600281555a60405161016b81611c2c565b6001600160a01b038416808252604435602083018190526064356040938401819052600280546001600160a81b03191690931760a09290921b60ff60a01b169190911791829055600355600480546001600160a01b031916331790559051906101d382611c8b565b6001825260208201906020368337737fc66500c84a76ad7e9c93437bfc5ac33e2ddae96101ff84611d6d565b526040519161020d83611c8b565b600183526020368185013760243561022484611d6d565b52604080516001600160a01b03891660208201529261024b9184019060a01c60ff16611dcb565b60643560608301526060825261026082611c70565b73ba12222222228d8ba445958a75a0704d566bf2c83b1561043957604051632e1c224f60e11b815230600482015260806024820152935160848501819052869385939092909160a485019190865b8181106104145750505060031984820301604485015260208084519283815201930190855b8181106103f85750505082820360031901606484015282916102f491611e11565b03818373ba12222222228d8ba445958a75a0704d566bf2c85af180156103ed576103d5575b506080926040519261032a84611c70565b60ff600554161515845260016006549160208601928352600754936040870194855261036160085496606089019788525a90611d90565b908187528451916040519261037884604435611dcb565b602435602085015260408401526060830152838060a01b0316907fdc5019d79074cd354a501d0301da4a3d55c05c601593f6e2da04de191ae9337c893392a355604051935115158452516020840152516040830152516060820152f35b6103df8391611c5d565b6103e95783610319565b5080fd5b6040513d85823e3d90fd5b82518552899650879550602094850194909201916001016102d3565b82516001600160a01b031684528a9750889650602093840193909201916001016102ae565b8580fd5b604051633ee5aeb560e01b8152600490fd5b34610109576080366003190112610109576004356001600160401b0381116103e957366023820112156103e9578060040135906024602061048f84611cc7565b61049c6040519182611ca6565b848152019260051b82010190368211610def57602401915b81831061195657836024356001600160401b0381116103e9576104db903690600401611cde565b6044356001600160401b038111610ecd576104fa903690600401611cde565b90606435906001600160401b038211610def5736602383011215610def578160040135918461052884611d3e565b916105366040519384611ca6565b84835260208301943660248284010111610ecd578060246020930187378301015273ba12222222228d8ba445958a75a0704d566bf2c8330361191b57606081805181010312611917576105946040519361058f85611c2c565b611d59565b835260408101519160028310156104395760606105c0926105c794602087015201516040850152611d6d565b5192611d6d565b518201808311611903578151604051906001600160a01b031660a082016001600160401b038111838210176118ef57604052856020830152856040830152856060830152856080830152808252604051624d7b0960e81b8152602081600481855afa9081156115b35787916118b1575b5060405163625048e960e11b815290602082600481865afa9182156118a6578892611866575b506001600160a01b038116737fc66500c84a76ad7e9c93437bfc5ac33e2ddae90361174457604051630315311560e31b815260048101899052908882602481875afa91821561173957899261171c575b50604051630315311560e31b815260016004820152918983602481885afa908115611711577340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f938b926116f4575b506001600160a01b0390811660208801521660408601525b6001600160a01b0316036115e85750604051630315311560e31b81526004810187905290868083602481855afa9182156115db5760249382936115be575b50604051630315311560e31b81526001600482015293849182905afa9182156115b357879261158e575b506001600160a01b0390811660608401521660808201525b602081015161079e906001600160a01b0316611ec2565b60408101516107b5906001600160a01b0316611ec2565b60608101516107cc906001600160a01b0316611ec2565b60808101516107e3906001600160a01b0316611ec2565b6020830151600281101561157a5785919061101a5780516001600160a01b031673ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b15610ecd57604051906301abf04560e71b82526004820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9602482015285604482015282816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af19081156103ed578391611006575b50506020818101516040516370a0823160e01b81523060048201529190829060249082906001600160a01b03165afa9081156103ed578391610fd1575b5080610faa575b5060408181015190516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103ed578391610f75575b5080610f4e575b5060608101516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103ed578391610f19575b5060808201516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa908115610f0e578491610ed9575b5080821015610ed15750905b81610e33575b50506040516370a0823160e01b81523060048201526020816024817340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f5afa908115610df3578291610dfe575b5080610c9e575b50505b6040516370a0823160e01b8152306004820152602081602481737fc66500c84a76ad7e9c93437bfc5ac33e2ddae95afa908115610bcb578591610c67575b50818110610c1e576040610a2c8383611d90565b9301518310610bd6575060405163a9059cbb60e01b9182825273ba12222222228d8ba445958a75a0704d566bf2c86004830152602482015260208160448188737fc66500c84a76ad7e9c93437bfc5ac33e2ddae95af18015610bcb57610b9c575b5081610ad0575b50826060604051610aa481611c70565b600181528360208201528460408201520152600160ff1960055416176005556006556007558060085580f35b60045460405160208082019384526001600160a01b039092166024820152604481018490529091600091610b1181606481015b03601f198101835282611ca6565b519082737fc66500c84a76ad7e9c93437bfc5ac33e2ddae95af115610b90576000513d610b875750737fc66500c84a76ad7e9c93437bfc5ac33e2ddae93b155b610b5b5783610a94565b604051635274afe760e01b8152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae96004820152602490fd5b60011415610b51565b6040513d6000823e3d90fd5b610bbd9060203d602011610bc4575b610bb58183611ca6565b810190611db3565b5084610a8d565b503d610bab565b6040513d87823e3d90fd5b60a49160405191633566cf0d60e01b83526004830152602482015260606044820152601460648201527350726f6669742062656c6f77206d696e696d756d60601b6084820152fd5b60a49160405191633566cf0d60e01b835260048301526024820152606060448201526015606482015274496e73756666696369656e7420746f20726570617960581b6084820152fd5b90506020813d602011610c96575b81610c8260209383611ca6565b81010312610c91575185610a18565b600080fd5b3d9150610c75565b6040517340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f60601b6020820152607d60ea1b603482018190527314170d3238c43166d83a33a945d3d619c6c0dd6960631b6037830152604b820152736015551cd911ff4685072e2793f56c841e3ab66160611b604e82015261017760eb1b6062820152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae960601b60658201526059815290610d5690610d4383611c70565b610b0360405193849230602085016121b4565b6040519082602083015260018252610d6d82611c8b565b610d756121eb565b90610d7f82611d6d565b52610d8981611d6d565b507366a9893cc07d91d95644aedd05d03f95e1dba8af91823b15610def57610dcc92849283604051809681958294630d64d59360e21b8452429160048501612220565b03925af18015610df357156109d757610de490611c5d565b610def5783856109d7565b8380fd5b6040513d84823e3d90fd5b9150506020813d602011610e2b575b81610e1a60209383611ca6565b81010312610c9157849051866109d0565b3d9150610e0d565b516001600160a01b03169073ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b15610ecd5760405191637abef8d160e01b835260048301527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6024830152604482015281816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af18015610df357610eb9575b80610990565b610ec290611c5d565b610def578385610eb3565b8280fd5b90509061098a565b9350506020833d602011610f06575b81610ef560209383611ca6565b81010312610c91578692518861097e565b3d9150610ee8565b6040513d86823e3d90fd5b9250506020823d602011610f46575b81610f3560209383611ca6565b81010312610c915785915187610941565b3d9150610f28565b60408201516080830151610f6f92916001600160a01b03918216911661229d565b86610904565b9250506020823d602011610fa2575b81610f9160209383611ca6565b81010312610c9157859151876108fd565b3d9150610f84565b60208201516060830151610fcb92916001600160a01b03918216911661229d565b866108c0565b9250506020823d602011610ffe575b81610fed60209383611ca6565b81010312610c9157859151876108b9565b3d9150610fe0565b61100f90611c5d565b6103e957818761087c565b604051737fc66500c84a76ad7e9c93437bfc5ac33e2ddae960601b602082015261017760eb1b6034820152736015551cd911ff4685072e2793f56c841e3ab66160611b6037820152607d60ea1b604b82018190527314170d3238c43166d83a33a945d3d619c6c0dd6960631b604e83015260628201527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f60601b606582015260598152909150610b03906110d6906110c581611c70565b6040519283918830602085016121b4565b85604051816020820152600181526110ed81611c8b565b6110f56121eb565b926110ff84611d6d565b5261110983611d6d565b507366a9893cc07d91d95644aedd05d03f95e1dba8af3b156103e957604051630d64d59360e21b815292839182916111479142919060048501612220565b0381837366a9893cc07d91d95644aedd05d03f95e1dba8af5af1801561156f5761155c575b506040516370a0823160e01b81523060048201528591906020816024817340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f5afa9081156103ed578391611527575b5081516001600160a01b03169073ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b15610def57604051916301abf04560e71b835260048301527340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6024830152604482015282816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af19081156103ed578391611513575b505060608101516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103ed5783916114de575b50806114b7575b5060808101516040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156103ed578391611482575b508061145b575b506020818101516040516370a0823160e01b81523060048201529190829060249082906001600160a01b03165afa9081156103ed578391611426575b5060408281015190516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa908115610f0e5784916113f1575b50808210156113e95750905b8161134f575b5050506109da565b516001600160a01b03169073ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc3b15610ecd5760405191637abef8d160e01b83526004830152737fc66500c84a76ad7e9c93437bfc5ac33e2ddae96024830152604482015281816064818373ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc5af18015610df3576113d5575b80611347565b6113de90611c5d565b610def5783856113cf565b905090611341565b9350506020833d60201161141e575b8161140d60209383611ca6565b81010312610c915786925188611335565b3d9150611400565b9250506020823d602011611453575b8161144260209383611ca6565b81010312610c9157859151876112f8565b3d9150611435565b6080820151604083015161147c92916001600160a01b03918216911661229d565b866112bc565b9250506020823d6020116114af575b8161149e60209383611ca6565b81010312610c9157859151876112b5565b3d9150611491565b606082015160208301516114d892916001600160a01b03918216911661229d565b86611278565b9250506020823d60201161150b575b816114fa60209383611ca6565b81010312610c915785915187611271565b3d91506114ed565b61151c90611c5d565b6103e9578187611233565b9250506020823d602011611554575b8161154360209383611ca6565b81010312610c9157859151876111ae565b3d9150611536565b61156890959195611c5d565b938561116c565b6040513d88823e3d90fd5b634e487b7160e01b86526021600452602486fd5b6115ab9192503d8089833e6115a38183611ca6565b810190611e36565b50908761076f565b6040513d89823e3d90fd5b6115d39193503d8084833e6115a38183611ca6565b509189610745565b50604051903d90823e3d90fd5b6001600160a01b03167340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f036116ba57604051630315311560e31b81526002600482015290868083602481855afa9182156115db57602493829361169d575b50604051630315311560e31b81526003600482015293849182905afa9182156115b3578792611680575b506001600160a01b039081166060840152166080820152610787565b6116959192503d8089833e6115a38183611ca6565b509087611664565b6116b29193503d8084833e6115a38183611ca6565b50918961163a565b60405162461bcd60e51b815260206004820152601260248201527111d213c81b9bdd0818dbdb1b185d195c985b60721b6044820152606490fd5b6117099192503d808d833e6115a38183611ca6565b50908b6106ef565b6040513d8c823e3d90fd5b6117319192503d808b833e6115a38183611ca6565b5090896106ad565b6040513d8b823e3d90fd5b6001600160a01b038216737fc66500c84a76ad7e9c93437bfc5ac33e2ddae90361182b57604051630315311560e31b815260026004820152908882602481875afa91821561173957899261180e575b50604051630315311560e31b815260036004820152918983602481885afa908115611711577340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f938b926117f1575b506001600160a01b039081166020880152166040860152610707565b6118069192503d808d833e6115a38183611ca6565b50908b6117d5565b6118239192503d808b833e6115a38183611ca6565b509089611793565b60405162461bcd60e51b815260206004820152601360248201527210505591481b9bdd0818dbdb1b185d195c985b606a1b6044820152606490fd5b9091506020813d60201161189e575b8161188260209383611ca6565b8101031261189a5761189390611d59565b908861065d565b8780fd5b3d9150611875565b6040513d8a823e3d90fd5b90506020813d6020116118e7575b816118cc60209383611ca6565b810103126118e3576118dd90611d59565b87610637565b8680fd5b3d91506118bf565b634e487b7160e01b87526041600452602487fd5b634e487b7160e01b84526011600452602484fd5b8480fd5b60405162461bcd60e51b815260206004820152601360248201527213db9b1e4810985b185b98d95c8815985d5b1d606a1b6044820152606490fd5b82356001600160a01b0381168103611917578152602092830192016104b4565b3461010957806003193601126101095760206040517340d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f8152f35b34610109578060031936011261010957602060405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28152f35b34610109578060031936011261010957602060405173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488152f35b346101095780600319360112610109576020604051737fc66500c84a76ad7e9c93437bfc5ac33e2ddae98152f35b346101095780600319360112610109576020604051610bb88152f35b34610109578060031936011261010957602090604051908152f35b3461010957806003193601126101095760206040517366a9893cc07d91d95644aedd05d03f95e1dba8af8152f35b34610109578060031936011261010957602060405173ba12222222228d8ba445958a75a0704d566bf2c88152f35b3461010957806003193601126101095760206040516e22d473030f116ddee9f6b43ac78ba38152f35b34610109578060031936011261010957602060405173ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc8152f35b346103e95760403660031901126103e957611b31611bf9565b60018060a01b0390816001541692833303611bca575060405163a9059cbb60e01b60208281019182526001600160a01b03909516602480840191909152356044830152919092169291849190611b8a8160648101610b03565b519082855af1156115db5781513d611bc15750803b155b611ba9575080f35b60249060405190635274afe760e01b82526004820152fd5b60011415611ba1565b62461bcd60e51b815260206004820152600a60248201526941646d696e206f6e6c7960b01b6044820152606490fd5b600435906001600160a01b0382168203610c9157565b34610c91576000366003190112610c915760206040516101f48152f35b606081019081106001600160401b03821117611c4757604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b038111611c4757604052565b608081019081106001600160401b03821117611c4757604052565b604081019081106001600160401b03821117611c4757604052565b90601f801991011681019081106001600160401b03821117611c4757604052565b6001600160401b038111611c475760051b60200190565b9080601f83011215610c91576020908235611cf881611cc7565b93611d066040519586611ca6565b81855260208086019260051b820101928311610c9157602001905b828210611d2f575050505090565b81358152908301908301611d21565b6001600160401b038111611c4757601f01601f191660200190565b51906001600160a01b0382168203610c9157565b805115611d7a5760200190565b634e487b7160e01b600052603260045260246000fd5b91908203918211611d9d57565b634e487b7160e01b600052601160045260246000fd5b90816020910312610c9157518015158103610c915790565b906002821015611dd85752565b634e487b7160e01b600052602160045260246000fd5b60005b838110611e015750506000910152565b8181015183820152602001611df1565b90602091611e2a81518092818552858086019101611dee565b601f01601f1916010190565b9190604083820312610c915782516001600160a01b0381168103610c9157926020810151906001600160401b038211610c91570181601f82011215610c91578051611e8081611d3e565b92611e8e6040519485611ca6565b81845260208284010111610c9157611eac9160208085019101611dee565b90565b519065ffffffffffff82168203610c9157565b60018060a01b0380911660408051636eb1769f60e11b9283825260049330858401526e22d473030f116ddee9f6b43ac78ba3602495818786015260209760449289878581895afa80156121a957600097889161217c575b5015612123575b87519063927da10560e01b82523084830152868a8301527366a9893cc07d91d95644aedd05d03f95e1dba8af918286820152606081606481855afa908115612119579084918a916120b8575b50161561205a575b5050508551928352308184015273ac9bf8eba6bd31f8e8c76f8e8b2aad0bd93f98dc92838882015288818481885afa908115612050578691612023575b5015611fc2575b5050505050505050565b8488948751988995869463095ea7b360e01b8652850152600019908401525af1918215612019575050611ffb575b808080808080611fb8565b8161201192903d10610bc457610bb58183611ca6565b503880611ff0565b51903d90823e3d90fd5b90508881813d8311612049575b61203a8183611ca6565b81010312610c91575138611fb1565b503d612030565b87513d88823e3d90fd5b803b1561189a579060848a8980948c5196879586946387517c4560e01b86528d8b8701528501528984015265ffffffffffff60648401525af18015612050576120a5575b8080611f74565b6120b190959195611c5d565b933861209e565b9150506060813d606011612111575b816120d460609383611ca6565b8101031261210d57805190848216820361210957906121028b838f6120fb90899601611eaf565b5001611eaf565b5038611f6c565b8980fd5b8880fd5b3d91506120c7565b8a513d8b823e3d90fd5b875163095ea7b360e01b81528381018290526000198a8201528a8186818b8b5af1801561217257612155575b50611f20565b61216b908b3d8d11610bc457610bb58183611ca6565b503861214f565b89513d8a823e3d90fd5b90508a81813d83116121a2575b6121938183611ca6565b8101031261189a575138611f19565b503d612189565b88513d6000823e3d90fd5b93926121e690600193608093858060a01b0316875260208701526000604087015260a0606087015260a0860190611e11565b930152565b6040516121f781611c8b565b600181528060005b60208082101561221a579060606020928285010152016121ff565b50505090565b9392919061223690606086526060860190611e11565b906020858303818701528151908184528084019381808460051b8301019401946000915b84831061226f57505050505060409150930152565b9091929394848061228c600193601f198682030187528a51611e11565b98019301930191959493929061225a565b91612302919392604051946bffffffffffffffffffffffff19809260601b166020870152607d60ea1b603487015260601b166037850152602b84526122e184611c2c565b6122f460405194859230602085016121b4565b03601f198101845283611ca6565b604051916000908160208501526001845261231c84611c8b565b6123246121eb565b9061232e82611d6d565b5261233881611d6d565b507366a9893cc07d91d95644aedd05d03f95e1dba8af90813b15610ecd5793829161237d949583604051809781958294630d64d59360e21b8452429160048501612220565b03925af190811561239b57506123905750565b61239990611c5d565b565b604051903d90823e3d90fdfea26469706673582212208946ef5cc84f2cda70da7a86c22cab1163dd3f5e35b90f347955897c66c6b90364736f6c63430008180033
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
[ Download: CSV Export ]
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.