Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Latest 25 from a total of 73 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw | 24396152 | 16 days ago | IN | 0 ETH | 0.00006746 | ||||
| Withdraw | 24396129 | 16 days ago | IN | 0 ETH | 0.00002929 | ||||
| Withdraw | 24396063 | 16 days ago | IN | 0 ETH | 0.00002797 | ||||
| Withdraw | 24396054 | 16 days ago | IN | 0 ETH | 0.00003764 | ||||
| Withdraw | 24395992 | 16 days ago | IN | 0 ETH | 0.00003692 | ||||
| Execute Arbitrag... | 22986723 | 213 days ago | IN | 0 ETH | 0.00055104 | ||||
| Execute Multi Ar... | 22981555 | 214 days ago | IN | 0 ETH | 0.00297311 | ||||
| Transfer | 22981117 | 214 days ago | IN | 0.001 ETH | 0.00005702 | ||||
| Transfer | 22981018 | 214 days ago | IN | 0.001 ETH | 0.00005747 | ||||
| Execute Arbitrag... | 22980907 | 214 days ago | IN | 0 ETH | 0.00136271 | ||||
| Execute Arbitrag... | 22980793 | 214 days ago | IN | 0 ETH | 0.00034279 | ||||
| Execute Arbitrag... | 22980692 | 214 days ago | IN | 0 ETH | 0.00130843 | ||||
| Execute Multi Ar... | 22980331 | 214 days ago | IN | 0 ETH | 0.00333499 | ||||
| Execute Arbitrag... | 22980074 | 214 days ago | IN | 0 ETH | 0.00032726 | ||||
| Execute Multi Ar... | 22974734 | 215 days ago | IN | 0 ETH | 0.00319813 | ||||
| Execute Arbitrag... | 22974530 | 215 days ago | IN | 0 ETH | 0.00042675 | ||||
| Execute Arbitrag... | 22974521 | 215 days ago | IN | 0 ETH | 0.00041615 | ||||
| Execute Arbitrag... | 22974508 | 215 days ago | IN | 0 ETH | 0.00039757 | ||||
| Execute Arbitrag... | 22974504 | 215 days ago | IN | 0 ETH | 0.0003727 | ||||
| Execute Arbitrag... | 22974490 | 215 days ago | IN | 0 ETH | 0.00037821 | ||||
| Execute Arbitrag... | 22974471 | 215 days ago | IN | 0 ETH | 0.00040377 | ||||
| Execute Arbitrag... | 22974461 | 215 days ago | IN | 0 ETH | 0.00044065 | ||||
| Withdraw | 22974426 | 215 days ago | IN | 0 ETH | 0.00014442 | ||||
| Withdraw | 22974409 | 215 days ago | IN | 0 ETH | 0.00004056 | ||||
| Execute Multi Ar... | 22973536 | 215 days ago | IN | 0 ETH | 0.00106763 |
Latest 5 internal transactions
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SecureArbitrageContractV4
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 2000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
//Router Interface
interface IUniswapV2Router {
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
}
interface I1InchV6 {
function swap(
address executor,
address srcToken,
address dstToken,
uint256 amount,
uint256 minReturn,
bytes calldata data
) external returns (uint256 returnAmount);
}
contract SecureArbitrageContractV4 is
AccessControl,
ReentrancyGuard,
Pausable
{
using SafeERC20 for IERC20;
// ═══════════════════════════════════════════════════════════════════
// ROLES & CONSTANTS
// ═══════════════════════════════════════════════════════════════════
bytes32 public constant BOT_ROLE = keccak256("BOT_ROLE");
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
uint256 public constant MAX_SLIPPAGE = 500; // 5%
uint256 public constant MIN_PROFIT_BASIS_POINTS = 10; // 0.1%
uint256 public constant MAX_TOKENS_PER_ARBITRAGE = 10;
uint256 public constant DEFAULT_MAX_ALLOWANCE_USDC = 10000 * 1e6;
uint256 public constant DEFAULT_MAX_TRADE_AMOUNT_USDC = 5000 * 1e6;
// ═══════════════════════════════════════════════════════════════════
// STRUCTS (OPTIMIZED)
// ═══════════════════════════════════════════════════════════════════
struct Config {
uint256 minProfitThreshold;
uint256 maxSlippage;
uint256 maxGasPrice;
uint256 maxTradeAmountUSDC;
uint256 maxRouterAllowanceUSDC;
bool emergencyMode;
bool strictSelectorValidation; // New: toggle for selector validation
}
struct TradeState {
bool inTrade;
uint256 tradeStartTime;
address initiator;
uint256 nonce;
}
struct AssetInfo {
uint256 maxTradeAmount;
bool isActive;
uint8 decimals;
bytes32 symbolHash;
}
// ═══════════════════════════════════════════════════════════════════
// STATE VARIABLES
// ═══════════════════════════════════════════════════════════════════
Config public config;
TradeState public tradeState;
uint256 public totalProfit;
uint256 public totalTrades;
uint8 public deploymentCount;
// Selector validation
mapping(bytes4 => bool) public validSelectors;
mapping(bytes4 => string) public selectorNames;
bytes4[] public allSelectors;
// Simplified mappings (removed multi-sig related)
mapping(address => bool) public activeBots;
mapping(address => bool) public approvedRouters;
mapping(address => AssetInfo) public assetConfigs;
mapping(address => bool) public approvedTokens;
// Arrays for enumeration
address[] public allBots;
address[] public allRouters;
address[] public allTokens;
// ═══════════════════════════════════════════════════════════════════
// EVENTS
// ═══════════════════════════════════════════════════════════════════
event ArbitrageExecuted(
address indexed tokenIn,
address indexed tokenOut,
uint256 amountIn,
uint256 profit,
address indexed routerUsed,
address executor
);
event AssetUpdated(address indexed asset, uint256 maxTrade, bool isActive, string assetType);
event BotUpdated(address indexed bot, bool isActive);
event SelectorUpdated(bytes4 indexed selector, bool isValid, string name);
event Withdrawal(address indexed token, uint256 amount, address indexed recipient);
// ═══════════════════════════════════════════════════════════════════
// MODIFIERS
// ═══════════════════════════════════════════════════════════════════
modifier onlyActiveBot() {
require(hasRole(BOT_ROLE, msg.sender) && activeBots[msg.sender], "Not active bot");
_;
}
modifier validAsset(address asset, bool isToken) {
if (isToken) {
require(approvedTokens[asset] && assetConfigs[asset].isActive, "Invalid token");
} else {
require(approvedRouters[asset] && assetConfigs[asset].isActive, "Invalid router");
}
_;
}
modifier notInTrade() {
require(!tradeState.inTrade, "Trade in progress");
_;
}
modifier gasLimit() {
require(tx.gasprice <= config.maxGasPrice, "Gas price too high");
_;
}
// ═══════════════════════════════════════════════════════════════════
// CONSTRUCTOR
// ═══════════════════════════════════════════════════════════════════
constructor(
address _admin,
address _operator,
uint256 _minProfitThreshold,
address[] memory _botAddresses
) {
require(_admin != address(0) && _operator != address(0), "Invalid addresses");
_grantRole(DEFAULT_ADMIN_ROLE, _admin);
_grantRole(OPERATOR_ROLE, _operator);
config = Config({
minProfitThreshold: _minProfitThreshold,
maxSlippage: 300,
maxGasPrice: 100 gwei,
maxTradeAmountUSDC: DEFAULT_MAX_TRADE_AMOUNT_USDC,
maxRouterAllowanceUSDC: DEFAULT_MAX_ALLOWANCE_USDC,
emergencyMode: false,
strictSelectorValidation: true // Enable by default
});
tradeState.nonce = 1;
deploymentCount++;
_initializeDefaults();
_initializeBots(_botAddresses);
_initializeSelectors();
}
// ═══════════════════════════════════════════════════════════════════
// CORE ARBITRAGE FUNCTIONS
// ═══════════════════════════════════════════════════════════════════
function executeArbitrage(
address tokenIn,
address tokenOut,
uint256 amountIn,
address targetRouter,
bytes memory swapData,
uint256 minReturn
)
external
payable
onlyActiveBot
nonReentrant
whenNotPaused
notInTrade
validAsset(targetRouter, false)
validAsset(tokenIn, true)
validAsset(tokenOut, true)
gasLimit
{
require(amountIn > 0 && amountIn <= assetConfigs[tokenIn].maxTradeAmount, "Invalid amount");
require(amountIn <= assetConfigs[targetRouter].maxTradeAmount, "Exceeds router limit");
_startTrade();
// Validate swap data if strict validation is enabled
if (config.strictSelectorValidation) {
_validateSwapData(tokenIn, tokenOut, amountIn, minReturn, targetRouter, swapData);
}
uint256 beforeBal = IERC20(tokenOut).balanceOf(address(this));
_executeSwap(targetRouter, swapData);
uint256 afterBal = IERC20(tokenOut).balanceOf(address(this));
require(afterBal >= minReturn, "Insufficient return");
uint256 profit = afterBal > beforeBal ? afterBal - beforeBal : 0;
if (profit >= config.minProfitThreshold) totalProfit += profit;
totalTrades++;
emit ArbitrageExecuted(tokenIn, tokenOut, amountIn, profit, targetRouter, msg.sender);
_endTrade();
}
function executeMultiArbitrage(
address[] calldata tokens,
uint256 amountIn,
address[] calldata routers,
bytes[] calldata datas,
uint256 minReturn
)
external
payable
onlyActiveBot
nonReentrant
whenNotPaused
notInTrade
gasLimit
{
require(tokens.length >= 3 && tokens.length <= MAX_TOKENS_PER_ARBITRAGE, "Invalid tokens length");
require(routers.length == tokens.length - 1 && datas.length == routers.length, "Mismatched arrays");
require(amountIn <= assetConfigs[tokens[0]].maxTradeAmount, "Amount exceeds limit");
// Validate all assets
for (uint i = 0; i < tokens.length; i++) {
require(approvedTokens[tokens[i]] && assetConfigs[tokens[i]].isActive, "Invalid token");
}
for (uint i = 0; i < routers.length; i++) {
require(approvedRouters[routers[i]] && assetConfigs[routers[i]].isActive, "Invalid router");
}
_startTrade();
uint256 beforeBal = IERC20(tokens[0]).balanceOf(address(this));
uint256 currentAmount = amountIn;
for (uint i = 0; i < routers.length; i++) {
if (i > 0) {
currentAmount = IERC20(tokens[i]).balanceOf(address(this));
}
bytes memory modifiedData = _updateSwapAmount(datas[i], currentAmount);
// Validate if strict validation is enabled
if (config.strictSelectorValidation) {
_validateSwapData(
tokens[i],
tokens[i + 1],
currentAmount,
0,
routers[i],
modifiedData
);
}
_executeSwap(routers[i], modifiedData);
}
uint256 afterBal = IERC20(tokens[0]).balanceOf(address(this));
require(afterBal >= minReturn, "Insufficient return");
uint256 profit = afterBal > beforeBal ? afterBal - beforeBal : 0;
if (profit >= config.minProfitThreshold) totalProfit += profit;
totalTrades++;
emit ArbitrageExecuted(tokens[0], tokens[0], amountIn, profit, address(0), msg.sender);
_endTrade();
}
// ═══════════════════════════════════════════════════════════════════
// INTERNAL HELPER FUNCTIONS
// ═══════════════════════════════════════════════════════════════════
function _validateSwapData(
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 minReturn,
address router,
bytes memory data
) internal view {
require(data.length >= 4, "Invalid data length");
bytes4 sig;
assembly {
sig := mload(add(data, 32))
}
// Check if selector is valid (if strict validation is enabled)
require(validSelectors[sig], "Invalid function selector");
// Basic validation based on known selectors
if (sig == 0x38ed1739) { // uniswap_swapExactTokensForTokens
(
uint256 inAmt,
uint256 outMin,
address[] memory path,
address to,
uint256 deadline
) = abi.decode(
sliceBytes(data, 4, data.length - 4),
(uint256, uint256, address[], address, uint256)
);
require(path.length >= 2, "Invalid path length");
require(path[0] == tokenIn && path[path.length - 1] == tokenOut, "Invalid path");
require(to == address(this), "Invalid recipient");
require(inAmt == amountIn, "Wrong amountIn");
require(deadline > block.timestamp, "Expired deadline");
if (minReturn > 0) {
require(outMin >= minReturn, "Insufficient minReturn");
}
}
// Add more specific validations for other selectors as needed
}
function sliceBytes(bytes memory data, uint256 start, uint256 length) internal pure returns (bytes memory) {
require(data.length >= start + length, "sliceBytes: out of bounds");
bytes memory result = new bytes(length);
for (uint256 i = 0; i < length; i++) {
result[i] = data[start + i];
}
return result;
}
function _updateSwapAmount(bytes memory data, uint256 newAmountIn) internal pure returns (bytes memory) {
require(data.length >= 4, "Invalid swap data");
bytes4 sig;
assembly {
sig := mload(add(data, 32))
}
// Handle different selectors
if (sig == 0x38ed1739) { // uniswap_swapExactTokensForTokens
(
,
uint256 outMin,
address[] memory path,
address to,
uint256 deadline
) = abi.decode(sliceBytes(data, 4, data.length - 4), (uint256, uint256, address[], address, uint256));
return abi.encodeWithSelector(sig, newAmountIn, outMin, path, to, deadline);
}
else if (sig == 0x12aa3caf || sig == 0x7c025200) { // 1inch swap variants
// Generic handling for 1inch - you may need to adjust based on specific function
(
address executor,
address src,
address dst,
,
uint256 minReturn,
bytes memory swapData
) = abi.decode(sliceBytes(data, 4, data.length - 4), (address, address, address, uint256, uint256, bytes));
return abi.encodeWithSelector(sig, executor, src, dst, newAmountIn, minReturn, swapData);
}
// For unknown selectors, return original data (fallback)
return data;
}
function _executeSwap(address router, bytes memory data) internal {
(bool success, ) = router.call{value: msg.value}(data);
require(success, "Swap failed");
}
function _startTrade() internal {
tradeState = TradeState({
inTrade: true,
tradeStartTime: block.timestamp,
initiator: msg.sender,
nonce: tradeState.nonce + 1
});
}
function _endTrade() internal {
tradeState.inTrade = false;
tradeState.tradeStartTime = 0;
tradeState.initiator = address(0);
}
function _initializeDefaults() internal {
// Default routers
address[3] memory defaultRouters = [
0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, // Uniswap V2
0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F, // SushiSwap
0x111111125421cA6dc452d289314280a0f8842A65 // 1inch V6
];
for (uint i = 0; i < defaultRouters.length; i++) {
approvedRouters[defaultRouters[i]] = true;
assetConfigs[defaultRouters[i]] = AssetInfo({
maxTradeAmount: DEFAULT_MAX_TRADE_AMOUNT_USDC,
isActive: true,
decimals: 18,
symbolHash: keccak256(abi.encodePacked("ROUTER_", i))
});
allRouters.push(defaultRouters[i]);
}
// Default tokens
address[8] memory defaultTokens = [
0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48, // USDC
0xdAC17F958D2ee523a2206206994597C13D831ec7, // USDT
0x6B175474E89094C44Da98b954EedeAC495271d0F, // DAI
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, // WETH
0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0, // wstETH
0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599, // WBTC
0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32, // LDO
0x514910771AF9Ca656af840dff83E8264EcF986CA // LINK
];
uint8[8] memory decimals = [6, 6, 18, 18, 18, 8, 18, 18];
uint256[8] memory maxTrades = [
uint256(10000 * 1e6),
uint256(10000 * 1e6),
uint256(10000 * 1e18),
uint256(10 * 1e18),
uint256(10 * 1e18),
uint256(1 * 1e8),
uint256(100000 * 1e18),
uint256(1000 * 1e18)
];
for (uint i = 0; i < defaultTokens.length; i++) {
approvedTokens[defaultTokens[i]] = true;
assetConfigs[defaultTokens[i]] = AssetInfo({
maxTradeAmount: maxTrades[i],
isActive: true,
decimals: decimals[i],
symbolHash: keccak256(abi.encodePacked("TOKEN_", i))
});
allTokens.push(defaultTokens[i]);
}
}
function _initializeBots(address[] memory _botAddresses) internal {
for (uint i = 0; i < _botAddresses.length; i++) {
require(_botAddresses[i] != address(0), "Invalid bot");
_grantRole(BOT_ROLE, _botAddresses[i]);
activeBots[_botAddresses[i]] = true;
allBots.push(_botAddresses[i]);
emit BotUpdated(_botAddresses[i], true);
}
}
function _initializeSelectors() internal {
// Initialize with your provided selectors
bytes4[9] memory selectors = [
bytes4(0x12aa3caf), // 1inch_swap
bytes4(0xe449022e), // 1inch_uniswapV3Swap
bytes4(0x2e95b6c8), // 1inch_unoswap
bytes4(0x84bd6d29), // 1inch_clipperSwap
bytes4(0x7c025200), // 1inch_swap_v2
bytes4(0x0502b1c5), // 1inch_fillOrderRFQ
bytes4(0x38ed1739), // uniswap_swapExactTokensForTokens
bytes4(0x8803dbee), // uniswap_swapTokensForExactTokens
bytes4(0x2195995c) // Additional selector if needed
];
string[9] memory names = [
"1inch_swap",
"1inch_uniswapV3Swap",
"1inch_unoswap",
"1inch_clipperSwap",
"1inch_swap_v2",
"1inch_fillOrderRFQ",
"uniswap_swapExactTokensForTokens",
"uniswap_swapTokensForExactTokens",
"additional_selector"
];
for (uint i = 0; i < selectors.length; i++) {
if (selectors[i] != bytes4(0)) {
validSelectors[selectors[i]] = true;
selectorNames[selectors[i]] = names[i];
allSelectors.push(selectors[i]);
}
}
}
// ═══════════════════════════════════════════════════════════════════
// ADMIN FUNCTIONS (SIMPLIFIED)
// ═══════════════════════════════════════════════════════════════════
// Withdrawal function that works for both ETH and ERC20 tokens
function withdraw(address token, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (token == address(0)) {
// ETH withdrawal
require(address(this).balance >= amount, "Insufficient ETH balance");
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "ETH transfer failed");
} else {
// ERC20 token withdrawal
require(IERC20(token).balanceOf(address(this)) >= amount, "Insufficient token balance");
IERC20(token).safeTransfer(msg.sender, amount);
}
emit Withdrawal(token, amount, msg.sender);
}
// Emergency withdrawal (all balance)
function emergencyWithdraw(address token) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (token == address(0)) {
uint256 balance = address(this).balance;
(bool success, ) = msg.sender.call{value: balance}("");
require(success, "ETH transfer failed");
emit Withdrawal(token, balance, msg.sender);
} else {
uint256 balance = IERC20(token).balanceOf(address(this));
IERC20(token).safeTransfer(msg.sender, balance);
emit Withdrawal(token, balance, msg.sender);
}
}
// Selector management functions
function addSelector(bytes4 selector, string memory name) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(!validSelectors[selector], "Selector already exists");
validSelectors[selector] = true;
selectorNames[selector] = name;
allSelectors.push(selector);
emit SelectorUpdated(selector, true, name);
}
function removeSelector(bytes4 selector) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(validSelectors[selector], "Selector doesn't exist");
validSelectors[selector] = false;
selectorNames[selector] = "";
// Remove from array
for (uint i = 0; i < allSelectors.length; i++) {
if (allSelectors[i] == selector) {
allSelectors[i] = allSelectors[allSelectors.length - 1];
allSelectors.pop();
break;
}
}
emit SelectorUpdated(selector, false, "");
}
// Toggle strict selector validation
function toggleSelectorValidation(bool enabled) external onlyRole(DEFAULT_ADMIN_ROLE) {
config.strictSelectorValidation = enabled;
}
// Asset management
function addToken(address token, uint256 maxTradeAmount, uint8 decimals) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(token != address(0), "Invalid token address");
require(!approvedTokens[token], "Token already exists");
approvedTokens[token] = true;
assetConfigs[token] = AssetInfo({
maxTradeAmount: maxTradeAmount,
isActive: true,
decimals: decimals,
symbolHash: keccak256(abi.encodePacked("TOKEN_", allTokens.length))
});
allTokens.push(token);
emit AssetUpdated(token, maxTradeAmount, true, "TOKEN");
}
function addRouter(address router, uint256 maxTradeAmount) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(router != address(0), "Invalid router address");
require(!approvedRouters[router], "Router already exists");
approvedRouters[router] = true;
assetConfigs[router] = AssetInfo({
maxTradeAmount: maxTradeAmount,
isActive: true,
decimals: 18,
symbolHash: keccak256(abi.encodePacked("ROUTER_", allRouters.length))
});
allRouters.push(router);
emit AssetUpdated(router, maxTradeAmount, true, "ROUTER");
}
function updateAsset(address asset, uint256 maxTradeAmount, bool isActive) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(approvedTokens[asset] || approvedRouters[asset], "Asset not found");
assetConfigs[asset].maxTradeAmount = maxTradeAmount;
assetConfigs[asset].isActive = isActive;
emit AssetUpdated(asset, maxTradeAmount, isActive, approvedTokens[asset] ? "TOKEN" : "ROUTER");
}
function updateBot(address bot, bool isActive) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (isActive && !hasRole(BOT_ROLE, bot)) {
_grantRole(BOT_ROLE, bot);
allBots.push(bot);
} else if (!isActive && hasRole(BOT_ROLE, bot)) {
_revokeRole(BOT_ROLE, bot);
}
activeBots[bot] = isActive;
emit BotUpdated(bot, isActive);
}
function approveToken(address token, address spender, uint256 amount) external onlyRole(OPERATOR_ROLE) {
IERC20(token).safeIncreaseAllowance(spender, amount);
}
function pause() external onlyRole(OPERATOR_ROLE) { _pause(); }
function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) { _unpause(); }
function forceUnlockTrade() external onlyRole(DEFAULT_ADMIN_ROLE) {
tradeState.inTrade = false;
tradeState.tradeStartTime = 0;
tradeState.initiator = address(0);
}
// ═══════════════════════════════════════════════════════════════════
// VIEW FUNCTIONS
// ═══════════════════════════════════════════════════════════════════
function getAllBots() external view returns (address[] memory) { return allBots; }
function getAllRouters() external view returns (address[] memory) { return allRouters; }
function getAllTokens() external view returns (address[] memory) { return allTokens; }
function getAllSelectors() external view returns (bytes4[] memory) { return allSelectors; }
function getSelectorName(bytes4 selector) external view returns (string memory) { return selectorNames[selector]; }
function isValidSelector(bytes4 selector) external view returns (bool) { return validSelectors[selector]; }
// ═══════════════════════════════════════════════════════════════════
// RECEIVE
// ═══════════════════════════════════════════════════════════════════
receive() external payable {}
fallback() external payable {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC-165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted to signal this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
* Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
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.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @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.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @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.3.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
bool private _paused;
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// 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": 2000
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_operator","type":"address"},{"internalType":"uint256","name":"_minProfitThreshold","type":"uint256"},{"internalType":"address[]","name":"_botAddresses","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","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":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"profit","type":"uint256"},{"indexed":true,"internalType":"address","name":"routerUsed","type":"address"},{"indexed":false,"internalType":"address","name":"executor","type":"address"}],"name":"ArbitrageExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"maxTrade","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"},{"indexed":false,"internalType":"string","name":"assetType","type":"string"}],"name":"AssetUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bot","type":"address"},{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"}],"name":"BotUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":false,"internalType":"bool","name":"isValid","type":"bool"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"SelectorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"Withdrawal","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"BOT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_MAX_ALLOWANCE_USDC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_MAX_TRADE_AMOUNT_USDC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SLIPPAGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOKENS_PER_ARBITRAGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_PROFIT_BASIS_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"activeBots","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"router","type":"address"},{"internalType":"uint256","name":"maxTradeAmount","type":"uint256"}],"name":"addRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"string","name":"name","type":"string"}],"name":"addSelector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"maxTradeAmount","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"addToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allBots","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allRouters","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allSelectors","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedRouters","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"assetConfigs","outputs":[{"internalType":"uint256","name":"maxTradeAmount","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"bytes32","name":"symbolHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"config","outputs":[{"internalType":"uint256","name":"minProfitThreshold","type":"uint256"},{"internalType":"uint256","name":"maxSlippage","type":"uint256"},{"internalType":"uint256","name":"maxGasPrice","type":"uint256"},{"internalType":"uint256","name":"maxTradeAmountUSDC","type":"uint256"},{"internalType":"uint256","name":"maxRouterAllowanceUSDC","type":"uint256"},{"internalType":"bool","name":"emergencyMode","type":"bool"},{"internalType":"bool","name":"strictSelectorValidation","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deploymentCount","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"targetRouter","type":"address"},{"internalType":"bytes","name":"swapData","type":"bytes"},{"internalType":"uint256","name":"minReturn","type":"uint256"}],"name":"executeArbitrage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"routers","type":"address[]"},{"internalType":"bytes[]","name":"datas","type":"bytes[]"},{"internalType":"uint256","name":"minReturn","type":"uint256"}],"name":"executeMultiArbitrage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"forceUnlockTrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllBots","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllRouters","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllSelectors","outputs":[{"internalType":"bytes4[]","name":"","type":"bytes4[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"getSelectorName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"isValidSelector","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"removeSelector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"selectorNames","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"toggleSelectorValidation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTrades","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradeState","outputs":[{"internalType":"bool","name":"inTrade","type":"bool"},{"internalType":"uint256","name":"tradeStartTime","type":"uint256"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"maxTradeAmount","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"}],"name":"updateAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bot","type":"address"},{"internalType":"bool","name":"isActive","type":"bool"}],"name":"updateBot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"validSelectors","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60808060405234610d215761528c803803809161001c8285610d79565b8339810190608081830312610d215761003481610d9c565b61004060208301610d9c565b6040830151606084015190936001600160401b038211610d2157019380601f86011215610d21578451946001600160401b0386116104e7578560051b906040519661008e6020840189610d79565b8752602080880192820101928311610d2157602001905b828210610d0957505060018055506001600160a01b038216151580610cf7575b15610cbe576100d66100dc92610db0565b50610e2c565b5060405160e081016001600160401b038111828210176104e75760019160c09160405283815261012c602082015264174876e800604082015264012a05f20060608201526402540be4006080820152600060a0820152015260035561012c60045564174876e80060055564012a05f2006006556402540be40060075560ff196008541660085561010061ff001960085416176008556001600c55600f5460ff811660ff8114610ca85760ff1990911660019190910160ff1617600f55604051606081016001600160401b038111828210176104e757604052737a250d5630b4cf539739df2c5dacb4c659f2488d815273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f602082015273111111125421ca6dc452d289314280a0f8842a65604082015260005b60038110610b48578260405161021781610d41565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48815273dac17f958d2ee523a2206206994597c13d831ec76020820152736b175474e89094c44da98b954eedeac495271d0f604082015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26060820152737f39c581f595b53c5cb19bd0b3f8da6c935e2ca06080820152732260fac5e5542a773aa44fbcfedf7c193bc2c59960a0820152735a98fcbea516cf06857215779fd812ca3bef1b3260c082015273514910771af9ca656af840dff83e8264ecf986ca60e0820152604051906102f182610d41565b6006825260066020830152601260408301526012606083015260126080830152600860a0830152601260c0830152601260e08301526040519161033383610d41565b6402540be40083526402540be400602084015269021e19e0c9bab24000006040840152678ac7230489e800006060840152678ac7230489e8000060808401526305f5e10060a084015269152d02c7e14af680000060c0840152683635c9adc5dea0000060e084015260005b600881106109d6578460005b8151811015610530576001600160a01b036103c58284610f7e565b5116156104fd576103e86001600160a01b036103e18385610f7e565b5116610ec4565b506001600160a01b036103fb8284610f7e565b51166000908152601360205260409020805460ff191660011790556001600160a01b036104288284610f7e565b51169060175491680100000000000000008310156104e75760018301806017558310156104d15760176000527fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c1590920180546001600160a01b0319169092179091556001906001600160a01b0361049f8285610f7e565b51167f1c6168ae13717a8cda4e1c9276a36c39333240268ba173a5a844201a8f4baa996020604051858152a2016103aa565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60405162461bcd60e51b815260206004820152600b60248201526a125b9d985b1a5908189bdd60aa1b6044820152606490fd5b60405161053c81610d5d565b6312aa3caf60e01b8152637224811760e11b60208201526305d2b6d960e31b6040808301919091526384bd6d2960e01b6060830152623e012960e91b6080830152630502b1c560e01b60a08301526338ed173960e01b60c0830152634401edf760e11b60e0830152630865665760e21b610100830152516105bc81610d5d565b6040516105ca604082610d79565b600a815269031696e63685f737761760b41b602082015281526040516105f1604082610d79565b601381527f31696e63685f756e6973776170563353776170000000000000000000000000006020820152602082015260405161062e604082610d79565b600d81526c031696e63685f756e6f7377617609c1b6020820152604082015260405161065b604082610d79565b6011815270031696e63685f636c69707065725377617607c1b6020820152606082015260405161068c604082610d79565b600d81526c18b4b731b42fb9bbb0b82fbb1960991b602082015260808201526040516106b9604082610d79565b601281527131696e63685f66696c6c4f7264657252465160701b602082015260a08201526040516106eb604082610d79565b602081527f756e69737761705f737761704578616374546f6b656e73466f72546f6b656e73602082015260c0820152604051610728604082610d79565b602081527f756e69737761705f73776170546f6b656e73466f724578616374546f6b656e73602082015260e0820152604051610765604082610d79565b601381527f6164646974696f6e616c5f73656c6563746f7200000000000000000000000000602082015261010082015260005b600981106107af576040516142689081610fa48239f35b6001600160e01b03196107c28285610f92565b51166107d1575b600101610798565b6001600160e01b03196107e48285610f92565b511660005260106020526040600020600160ff198254161790556108088183610f92565b516001600160e01b031961081c8386610f92565b51166000908152601160205260409020815190916001600160401b0382116104e757825490600182811c921680156109cc575b60208310146109b65781601f849311610963575b50602090601f83116001146108fe576000926108f3575b50508160011b916000199060031b1c19161790555b6108998184610f92565b5190601254680100000000000000008110156104e75760018101806012558110156104d157600192601260005260206000208260031c019163ffffffff60e084549260051b169260e01c831b921b191617905590506107c9565b01519050868061087a565b60008581528281209350601f198516905b81811061094b5750908460019594939210610932575b505050811b01905561088f565b015160001960f88460031b161c19169055868080610925565b9293602060018192878601518155019501930161090f565b909150836000526020600020601f840160051c810191602085106109ac575b90601f859493920160051c01905b81811061099d5750610863565b60008155849350600101610990565b9091508190610982565b634e487b7160e01b600052602260045260246000fd5b91607f169161084f565b6001600160a01b036109e88285610f6d565b511660005260166020526040600020600160ff19825416179055610a0c8185610f6d565b51600260ff610a1b8486610f6d565b5116604051602081019065544f4b454e5f60d01b825285602682015260268152610a46604682610d79565b5190209060405193610a5785610d26565b84526001602085019081526040850191825260608501928352906001600160a01b03610a83878a610f6d565b51166000526015602052604060002094518555610ab36001860192511515839060ff801983541691151516179055565b51815461ff00191660089190911b61ff0016179055519101556001600160a01b03610ade8285610f6d565b51169060195491680100000000000000008310156104e75760018301806019558310156104d15760196000527f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c969590920180546001600160a01b03191690921790915560010161039e565b6001600160a01b03610b5a8284610f5c565b511660005260146020526040600020600160ff19825416179055604051602081019066524f555445525f60c81b825282602782015260278152610b9e604782610d79565b519020600260405191610bb083610d26565b64012a05f2008352600160208401908152601260408501908152606085019283526001600160a01b03610be38789610f5c565b51166000526015602052604060002094518555610c136001860192511515839060ff801983541691151516179055565b51815461ff00191660089190911b61ff0016179055519101556001600160a01b03610c3e8284610f5c565b51169060185491680100000000000000008310156104e75760018301806018558310156104d15760186000527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e90920180546001600160a01b031916909217909155600101610202565b634e487b7160e01b600052601160045260246000fd5b60405162461bcd60e51b8152602060048201526011602482015270496e76616c69642061646472657373657360781b6044820152606490fd5b506001600160a01b03811615156100c5565b60208091610d1684610d9c565b8152019101906100a5565b600080fd5b608081019081106001600160401b038211176104e757604052565b61010081019081106001600160401b038211176104e757604052565b61012081019081106001600160401b038211176104e757604052565b601f909101601f19168101906001600160401b038211908210176104e757604052565b51906001600160a01b0382168203610d2157565b6001600160a01b038116600090815260008051602061526c833981519152602052604090205460ff16610e26576001600160a01b0316600081815260008051602061526c83398151915260205260408120805460ff1916600117905533919060008051602061520c8339815191528180a4600190565b50600090565b6001600160a01b038116600090815260008051602061524c833981519152602052604090205460ff16610e26576001600160a01b0316600081815260008051602061524c83398151915260205260408120805460ff191660011790553391907f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9299060008051602061520c8339815191529080a4600190565b6001600160a01b038116600090815260008051602061522c833981519152602052604090205460ff16610e26576001600160a01b0316600081815260008051602061522c83398151915260205260408120805460ff191660011790553391907f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b9060008051602061520c8339815191529080a4600190565b9060038110156104d15760051b0190565b9060088110156104d15760051b0190565b80518210156104d15760209160051b010190565b9060098110156104d15760051b019056fe60806040526004361015610018575b361561001657005b005b60003560e01c806301ffc9a71461033a578063083518381461033557806308dc0334146103305780630e2b0c941461032b5780630ffb3058146103265780631ba64197146102f95780631faee24f1461032157806322428b671461031c578063248a9ca3146103175780632a5c792a146103125780632ee773b51461030d5780632f2ff15d1461030857806336568abe146103035780633b2fda74146102fe5780633d2fe2fe146102f95780633f4ba83a146102f4578063445b1e4b146102ef5780634bbc0915146102ea5780634c36f10d146102e55780635c975abb146102e0578063634282af146102db578063672dbf55146102d657806367fc22c6146102d15780636d1ea3fa146102cc5780636ff1c9bc146102c757806371e259ed146102c25780637579a804146102b85780637609d7f6146102bd57806377dc3429146102b857806379502c55146102b35780637e8db6b31461024f5780638456cb59146102ae57806384f51b15146102a957806386001519146102a4578063864e18271461029f5780638b5b10641461029a57806391d1485414610295578063a030a8db14610290578063a217fddf1461028b578063a5218fd814610286578063b150377414610281578063d1a645041461027c578063d547741f14610277578063da3e339714610272578063db341d8c1461026d578063e275c99714610268578063f3fef3a314610263578063f5b541a61461025e578063f975951814610259578063fac1b9bc146102545763fe4906f10361000e575b611861565b612129565b61210c565b6120d1565b612012565b611ff4565b611e7c565b611daf565b611d6c565b611c22565b611be7565b611b8d565b611b71565b611af0565b611a68565b6119e8565b6119a3565b611985565b611940565b61187d565b611807565b611762565b6117a2565b611505565b6113ea565b6113a7565b611232565b611212565b6111b8565b611195565b611174565b611131565b6110d0565b61104e565b610bca565b611004565b610fa1565b610f59565b610e1f565b610d9f565b610d6a565b610d10565b610c6e565b610a86565b610a43565b610648565b6103f1565b61035b565b600435906001600160e01b03198216820361035657565b600080fd5b346103565760206003193601126103565760206001600160e01b031961037f61033f565b167f7965db0b0000000000000000000000000000000000000000000000000000000081149081156103b6575b506040519015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386103ab565b6001600160a01b0381160361035657565b346103565760406003193601126103565760043561040e816103e0565b7f4542bd31a6cc3179d1a1b1f87bd081e653199f97da71c0110ea63a86851575686105a160243561043d61328c565b6105566001600160a01b03851694610456861515612292565b61048c61048761048361047c846001600160a01b03166000526014602052604060002090565b5460ff1690565b1590565b6122dd565b6104b96104ac826001600160a01b03166000526014602052604060002090565b600160ff19825416179055565b61055160185460405161050c816104fe6020820194856027917f524f555445525f00000000000000000000000000000000000000000000000000825260078201520190565b03601f1981018352826105bc565b5190206105176105e4565b8581526001602082015290601260408301525b606082015261054c836001600160a01b03166000526015602052604060002090565b612328565b612373565b6040519182918260a09181526001602082015260606040820152600660608201527f524f55544552000000000000000000000000000000000000000000000000000060808201520190565b0390a2005b634e487b7160e01b600052604160045260246000fd5b90601f601f19910116810190811067ffffffffffffffff8211176105df57604052565b6105a6565b604051906105f36080836105bc565b565b67ffffffffffffffff81116105df57601f01601f191660200190565b92919261061d826105f5565b9161062b60405193846105bc565b829481845281830111610356578281602093846000960137010152565b60c060031936011261035657600435610660816103e0565b60243561066c816103e0565b6044359160643561067c816103e0565b60843567ffffffffffffffff81116103565736602382011215610356576106ad903690602481600401359101610611565b3360009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd9602052604090205490949060a4359060ff1680610a2a575b6106f59061247e565b6106fd61339f565b6107056133da565b61071460ff60095416156124c9565b6001600160a01b0383169586600052601460205260ff6040600020541680610a0f575b61074090612514565b6001600160a01b0385169485600052601660205260ff60406000205416806109f4575b61076c9061255f565b8183856001600160a01b038a16998a600052601660205260ff60406000205416806109d9575b61079b9061255f565b6107a96005543a11156125aa565b811515806109ad575b6107bb906125f5565b6107e46107db8a6001600160a01b03166000526015602052604060002090565b54831115612640565b6107ec613410565b60088054901c60ff1661099a575b50506040516370a0823160e01b8152306004820152969250602091508690506024818a5afa94851561096e57600095610973575b5090610839916139a7565b6040516370a0823160e01b815230600482015292602084602481895afa91821561096e577f98afc1d8e92542e983ad90a2aa1fb90d691c207e0366b4f158970a6b9bc4d73e94600093610939575b50610894908310156126a6565b60009181811115610932576108a99250612725565b600354811015610919575b6108c76108c2600e5461274d565b600e55565b6040805192835260208301919091523390820152606090a461091060ff19600954166009556000600a5573ffffffffffffffffffffffffffffffffffffffff19600b5416600b55565b61001660018055565b61092d61092882600d54612740565b600d55565b6108b4565b50506108a9565b6108949193506109609060203d602011610967575b61095881836105bc565b81019061268b565b9290610887565b503d61094e565b61269a565b610839929195506109929060203d6020116109675761095881836105bc565b94909161082e565b6109a3946138fc565b38818385836107fa565b506107bb6109ce866001600160a01b03166000526015602052604060002090565b5483111590506107b2565b5060008b81526015602052604090206001015460ff16610792565b5060008681526015602052604090206001015460ff16610763565b5060008781526015602052604090206001015460ff16610737565b503360009081526013602052604090205460ff166106ec565b34610356576020600319360112610356576001600160a01b03600435610a68816103e0565b166000526013602052602060ff604060002054166040519015158152f35b3461035657600060031936011261035657602060405164012a05f2008152f35b90600182811c92168015610ad6575b6020831014610ac057565b634e487b7160e01b600052602260045260246000fd5b91607f1691610ab5565b9060405191826000825492610af484610aa6565b8084529360018116908115610b605750600114610b19575b506105f3925003836105bc565b90506000929192526020600020906000915b818310610b445750509060206105f39282010138610b0c565b6020919350806001915483858901015201910190918492610b2b565b602093506105f395925060ff1991501682840152151560051b82010138610b0c565b60005b838110610b955750506000910152565b8181015183820152602001610b85565b90601f19601f602093610bc381518092818752878088019101610b82565b0116010190565b34610356576020600319360112610356576001600160e01b0319610bec61033f565b166000526011602052610c19610c056040600020610ae0565b604051918291602083526020830190610ba5565b0390f35b906020808351928381520192019060005b818110610c3b5750505090565b82516001600160a01b0316845260209384019390920191600101610c2e565b906020610c6b928181520190610c1d565b90565b346103565760006003193601126103565760405180602060185491828152019060186000527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e9060005b818110610cdb57610c1985610ccf818703826105bc565b60405191829182610c5a565b82546001600160a01b0316845260209093019260019283019201610cb8565b634e487b7160e01b600052603260045260246000fd5b3461035657602060031936011261035657600435601754811015610356576001600160a01b0360209160176000527fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c15015416604051908152f35b34610356576020600319360112610356576020610d97600435600052600060205260016040600020015490565b604051908152f35b346103565760006003193601126103565760405180602060195491828152019060196000527f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c96959060005b818110610e0057610c1985610ccf818703826105bc565b82546001600160a01b0316845260209093019260019283019201610de9565b3461035657604060031936011261035657610e3861033f565b60243567ffffffffffffffff8111610356573660238201121561035657610e69903690602481600401359101610611565b610e7161328c565b6001600160e01b031982169182600052601060205260ff60406000205416610f15577f2cfb492f2352fd3565cc68739c0c593565d69c709db710d0757167b8c39e689b91610f0982610edd6104ac6105a1956001600160e01b0319166000526010602052604060002090565b610f0483610eff836001600160e01b0319166000526011602052604060002090565b6127b8565b612889565b604051918291826128b3565b606460405162461bcd60e51b815260206004820152601760248201527f53656c6563746f7220616c7265616479206578697374730000000000000000006044820152fd5b3461035657604060031936011261035657610016602435600435610f7c826103e0565b610f9c610f9782600052600060205260016040600020015490565b613351565b613adf565b3461035657604060031936011261035657600435602435610fc1816103e0565b336001600160a01b03821603610fda5761001691613c4f565b7f6697b2320000000000000000000000000000000000000000000000000000000060005260046000fd5b346103565760006003193601126103565761101d61328c565b61001660ff19600954166009556000600a5573ffffffffffffffffffffffffffffffffffffffff19600b5416600b55565b346103565760006003193601126103565761106761328c565b60025460ff8116156110a65760ff19166002557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7f8dfc202b0000000000000000000000000000000000000000000000000000000060005260046000fd5b34610356576020600319360112610356576001600160a01b036004356110f5816103e0565b166000526014602052602060ff604060002054166040519015158152f35b60443590811515820361035657565b60243590811515820361035657565b34610356576020600319360112610356576004358015158091036103565761116f9061115b61328c565b6008805461ff00191691901b61ff00161790565b600855005b3461035657600060031936011261035657602060ff600f5416604051908152f35b3461035657600060031936011261035657602060ff600254166040519015158152f35b3461035657602060031936011261035657600435601954811015610356576001600160a01b0360209160196000527f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c9695015416604051908152f35b346103565760006003193601126103565760206040516402540be4008152f35b346103565760206003193601126103565761124b61033f565b61125361328c565b61127c61127761047c836001600160e01b0319166000526010602052604060002090565b6128cb565b6112a761129d826001600160e01b0319166000526010602052604060002090565b60ff198154169055565b6112cd6112c8826001600160e01b0319166000526011602052604060002090565b612916565b6001600160e01b03191660005b60125490818110156113a057826001600160e01b03196113096112fc846118d7565b90549060031b1c60e01b90565b16146113195760019150016112da565b6113396113336112fc61132e61135695612707565b6118d7565b916118d7565b90919063ffffffff83549160031b9260e01c831b921b1916179055565b61135e61294b565b7f2cfb492f2352fd3565cc68739c0c593565d69c709db710d0757167b8c39e689b604051806105a1816060906000815260406020820152600060408201520190565b505061135e565b34610356576020600319360112610356576001600160a01b036004356113cc816103e0565b166000526016602052602060ff604060002054166040519015158152f35b34610356576020600319360112610356576001600160a01b0360043561140f816103e0565b61141761328c565b1680611468574790611439600080808086335af161143361298e565b506129be565b60405191825233917e1a143d5b175701cb3246058ffac3d63945192075a926ff73a19930f09d587a90602090a3005b6040516370a0823160e01b815230600482015290602082602481845afa91821561096e576000926114a0575b50611439823383613cea565b6114ba91925060203d6020116109675761095881836105bc565b9038611494565b602060408183019282815284518094520192019060005b8181106114e55750505090565b82516001600160e01b0319168452602093840193909201916001016114d8565b3461035657600060031936011261035657604051601254808252906020810160126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444926000935b8160078601106116aa5791610c199484926115ac945491818110611686575b818110611667575b818110611648575b818110611629575b81811061160a575b8181106115eb575b8181106115cd575b106115b8575b5003826105bc565b604051918291826114c1565b6001600160e01b0319168152602001386115a4565b602083811b6001600160e01b0319168552909360019101930161159e565b604083901b6001600160e01b0319168452926001906020019301611596565b606083901b6001600160e01b031916845292600190602001930161158e565b608083901b6001600160e01b0319168452926001906020019301611586565b60a083901b6001600160e01b031916845292600190602001930161157e565b60c083901b6001600160e01b0319168452926001906020019301611576565b926020816116a26001938660e01b6001600160e01b0319169052565b01930161156e565b91600161010060089261175786546116ce838260e01b6001600160e01b0319169052565b60c081901b6001600160e01b031916602084015260a081901b6001600160e01b0319166040840152608081901b6001600160e01b0319166060840152606081901b6001600160e01b0319166080840152604081901b6001600160e01b03191660a0840152602081901b6001600160e01b03191660c08401526001600160e01b03191660e0830152565b01930194019361154f565b34610356576020600319360112610356576001600160e01b031961178461033f565b166000526010602052602060ff604060002054166040519015158152f35b34610356576020600319360112610356576001600160a01b036004356117c7816103e0565b1660005260156020526080604060002080549060ff60026001830154920154916040519384528181161515602085015260081c1660408301526060820152f35b346103565760006003193601126103565760e060035460ff60045460055460065460075491600854936040519687526020870152604086015260608501526080840152818116151560a084015260081c16151560c0820152f35b34610356576000600319360112610356576020604051600a8152f35b34610356576000600319360112610356576118966132df565b61189e6133da565b600160ff1960025416176002557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b90601254821015611918576012600052600382901c7fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444019160021b601c1690565b610cfa565b919091805483101561191857600052601c60206000208360031c019260021b1690565b3461035657602060031936011261035657600435601254811015610356576119696020916118d7565b90549060031b1c60e01b6001600160e01b031960405191168152f35b34610356576000600319360112610356576020600d54604051908152f35b3461035657600060031936011261035657608060ff60095416600a546001600160a01b03600b5416600c54916040519315158452602084015260408301526060820152f35b346103565760006003193601126103565760405180602060175491828152019060176000527fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c159060005b818110611a4957610c1985610ccf818703826105bc565b82546001600160a01b0316845260209093019260019283019201611a32565b3461035657604060031936011261035657602060ff611ab3602435600435611a8f826103e0565b600052600084526040600020906001600160a01b0316600052602052604060002090565b54166040519015158152f35b9181601f840112156103565782359167ffffffffffffffff8311610356576020808501948460051b01011161035657565b60a06003193601126103565760043567ffffffffffffffff811161035657611b1c903690600401611abf565b9060243560443567ffffffffffffffff811161035657611b40903690600401611abf565b606435949167ffffffffffffffff861161035657611b65610016963690600401611abf565b94909360843596612a09565b3461035657600060031936011261035657602060405160008152f35b3461035657602060031936011261035657600435601854811015610356576001600160a01b0360209160186000527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e015416604051908152f35b346103565760006003193601126103565760206040517f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b8152f35b3461035657606060031936011261035657600435611c3f816103e0565b7f4542bd31a6cc3179d1a1b1f87bd081e653199f97da71c0110ea63a8685157568602435611c6b611113565b90611c7461328c565b611d1561047c6001600160a01b0386169586600052601660205260ff604060002054168015611d41575b611ca790613081565b83611cc5826001600160a01b03166000526015602052604060002090565b55611cfc856001611ce9846001600160a01b03166000526015602052604060002090565b019060ff60ff1983541691151516179055565b6001600160a01b03166000526016602052604060002090565b15611d31576105a1611d25613107565b60405193849384613142565b6105a1611d3c6130cc565b611d25565b50611ca7611d6561047c836001600160a01b03166000526014602052604060002090565b9050611c9e565b3461035657604060031936011261035657610016602435600435611d8f826103e0565b611daa610f9782600052600060205260016040600020015490565b613c4f565b3461035657606060031936011261035657600435611dcc816103e0565b60243590611dd9826103e0565b6001600160a01b0360443591611ded6132df565b1691604051917fdd62ed3e0000000000000000000000000000000000000000000000000000000083523060048401526001600160a01b0382166024840152602083604481875afa92831561096e57600093611e5b575b508201809211611e565761001692614132565b6126f1565b611e7591935060203d6020116109675761095881836105bc565b9138611e43565b3461035657606060031936011261035657600435611e99816103e0565b6024356044359160ff83168303610356577f4542bd31a6cc3179d1a1b1f87bd081e653199f97da71c0110ea63a868515756891611fa96105a192611edb61328c565b611fa46001600160a01b03821696611ef4881515613160565b611f1f611f1a61048361047c866001600160a01b03166000526016602052604060002090565b6131ab565b611f3f6104ac846001600160a01b03166000526016602052604060002090565b601954604051611f81816104fe6020820194856026917f544f4b454e5f0000000000000000000000000000000000000000000000000000825260068201520190565b51902061052a611f8f6105e4565b878152600160208201529260ff166040840152565b6123cc565b6040519182918260a09181526001602082015260606040820152600560608201527f544f4b454e00000000000000000000000000000000000000000000000000000060808201520190565b34610356576000600319360112610356576020600e54604051908152f35b346103565760406003193601126103565760043561202f816103e0565b6001600160a01b036024359161204361328c565b16806120695761205582471015613241565b611439600080808086335af161143361298e565b6040516370a0823160e01b8152306004820152602081602481855afa90811561096e576120a29184916000916120b2575b5010156131f6565b6120ad823383613cea565b611439565b6120cb915060203d6020116109675761095881836105bc565b3861209a565b346103565760006003193601126103565760206040517f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9298152f35b346103565760006003193601126103565760206040516101f48152f35b3461035657604060031936011261035657600435612146816103e0565b7f1c6168ae13717a8cda4e1c9276a36c39333240268ba173a5a844201a8f4baa996001600160a01b03612177611122565b9261218061328c565b8380612248575b156121e65761219581613a0b565b5061219f81612425565b6121d2846121c0836001600160a01b03166000526013602052604060002090565b9060ff60ff1983541691151516179055565b6040519315158452169180602081016105a1565b831580612202575b1561219f576121fc81613b83565b5061219f565b506001600160a01b03811660009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd9602052604090206122439061047c565b6121ee565b506001600160a01b03811660009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd96020526040902061228d906104839061047c565b612187565b1561229957565b606460405162461bcd60e51b815260206004820152601660248201527f496e76616c696420726f757465722061646472657373000000000000000000006044820152fd5b156122e457565b606460405162461bcd60e51b815260206004820152601560248201527f526f7574657220616c72656164792065786973747300000000000000000000006044820152fd5b906060600291805184556001840161235360208301511515829060ff60ff1983541691151516179055565b6040820151815461ff00191660089190911b61ff00161790550151910155565b601854680100000000000000008110156105df57600181016018556000906018548110156119185760208260186001600160a01b0394522001911673ffffffffffffffffffffffffffffffffffffffff19825416179055565b601954680100000000000000008110156105df57600181016019556000906019548110156119185760208260196001600160a01b0394522001911673ffffffffffffffffffffffffffffffffffffffff19825416179055565b601754680100000000000000008110156105df57600181016017556000906017548110156119185760208260176001600160a01b0394522001911673ffffffffffffffffffffffffffffffffffffffff19825416179055565b1561248557565b606460405162461bcd60e51b815260206004820152600e60248201527f4e6f742061637469766520626f740000000000000000000000000000000000006044820152fd5b156124d057565b606460405162461bcd60e51b815260206004820152601160248201527f547261646520696e2070726f67726573730000000000000000000000000000006044820152fd5b1561251b57565b606460405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420726f757465720000000000000000000000000000000000006044820152fd5b1561256657565b606460405162461bcd60e51b815260206004820152600d60248201527f496e76616c696420746f6b656e000000000000000000000000000000000000006044820152fd5b156125b157565b606460405162461bcd60e51b815260206004820152601260248201527f47617320707269636520746f6f206869676800000000000000000000000000006044820152fd5b156125fc57565b606460405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420616d6f756e740000000000000000000000000000000000006044820152fd5b1561264757565b606460405162461bcd60e51b815260206004820152601460248201527f4578636565647320726f75746572206c696d69740000000000000000000000006044820152fd5b90816020910312610356575190565b6040513d6000823e3d90fd5b156126ad57565b606460405162461bcd60e51b815260206004820152601360248201527f496e73756666696369656e742072657475726e000000000000000000000000006044820152fd5b634e487b7160e01b600052601160045260246000fd5b906000198201918211611e5657565b906003198201918211611e5657565b91908203918211611e5657565b9060018201809211611e5657565b91908201809211611e5657565b6000198114611e565760010190565b818110612767575050565b6000815560010161275c565b9190601f811161278257505050565b6105f3926000526020600020906020601f840160051c830193106127ae575b601f0160051c019061275c565b90915081906127a1565b919091825167ffffffffffffffff81116105df576127e0816127da8454610aa6565b84612773565b6020601f8211600114612820578190612811939495600092612815575b50506000198260011b9260031b1c19161790565b9055565b0151905038806127fd565b601f1982169061283584600052602060002090565b9160005b81811061287157509583600195969710612858575b505050811b019055565b015160001960f88460031b161c1916905538808061284e565b9192602060018192868b015181550194019201612839565b60125490680100000000000000008210156105df576113398260016105f39401601255601261191d565b906040610c6b92600181528160208201520190610ba5565b156128d257565b606460405162461bcd60e51b815260206004820152601660248201527f53656c6563746f7220646f65736e2774206578697374000000000000000000006044820152fd5b6000906129238154610aa6565b601f811161292f575055565b8183526020832061294891601f0160051c81019061275c565b55565b6012548015612978576000190161296381601261191d565b63ffffffff82549160031b1b19169055601255565b634e487b7160e01b600052603160045260246000fd5b3d156129b9573d9061299f826105f5565b916129ad60405193846105bc565b82523d6000602084013e565b606090565b156129c557565b606460405162461bcd60e51b815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152fd5b3360009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd960205260409020549096919592949060ff1680612f04575b612a519061247e565b612a5961339f565b612a616133da565b612a7060ff60095416156124c9565b612a7e6005543a11156125aa565b600386101580612ef9575b612a9290612f1d565b612a9b86612707565b811480612ef0575b612aac90612f68565b612ae6612add612ac4612abf898b612fb3565b612fcc565b6001600160a01b03166000526015602052604060002090565b54861115612fd6565b60005b868110612e9f575060005b818110612e325750612b04613410565b612b23612b17612b17612abf898b612fb3565b6001600160a01b031690565b6040516370a0823160e01b81523060048201529490602090869060249082905afa94851561096e57600095612e11575b50859260005b838110612cde57505050505050612b79612b17612b17612abf8688612fb3565b6040516370a0823160e01b81523060048201529290602090849060249082905afa91821561096e57612c30612abf6001600160a01b0394612c609360009a7f98afc1d8e92542e983ad90a2aa1fb90d691c207e0366b4f158970a6b9bc4d73e988c93612cb9575b50612bed908310156126a6565b8a918181118c14612cb157612c029250612725565b965b600354881015612c9d575b612c1d6108c2600e5461274d565b612c2a612abf828b612fb3565b98612fb3565b9183604051948594169716953391849160409194936001600160a01b039160608501968552602085015216910152565b0390a4612c9460ff19600954166009556000600a5573ffffffffffffffffffffffffffffffffffffffff19600b5416600b55565b6105f360018055565b612cac61092889600d54612740565b612c0f565b505096612c04565b612bed919350612cd79060203d6020116109675761095881836105bc565b9290612be0565b89898783612d92575b8380938988612d4395612d1283612d0d612d068f999c8e60019e613021565b3691610611565b613e9d565b958694612d2560085460ff9060081c1690565b612d49575b50919050612abf9350612d3e949250612fbc565b6139a7565b01612b59565b86612d7f92612d79612abf84612d69612abf612d859d8a612abf99612fbc565b97612d7386612732565b91612fbc565b95612fbc565b506137cc565b8281898f8f8b8b92612d2a565b50829650612abf612daa93612b1792612b1794612fbc565b6040516370a0823160e01b81523060048201529490602090869060249082905afa94851561096e578285838d8a888f9b8497600091612df3575b509b9550509250935050612ce7565b612e0b915060203d81116109675761095881836105bc565b38612de4565b612e2b91955060203d6020116109675761095881836105bc565b9338612b53565b80612e6261047c612e49612abf600195878b612fbc565b6001600160a01b03166000526014602052604060002090565b80612e77575b612e7190612514565b01612af4565b50612e71612e9883612e90612ac4612abf86898d612fbc565b015460ff1690565b9050612e68565b80612ecb89828a612ebc61047c611cfc612abf6001998588612fbc565b9283612ed1575b50505061255f565b01612ae9565b612ee89350612abf8793612e9093612ac493612fbc565b828a8c612ec3565b50818114612aa3565b50600a861115612a89565b503360009081526013602052604090205460ff16612a48565b15612f2457565b606460405162461bcd60e51b815260206004820152601560248201527f496e76616c696420746f6b656e73206c656e67746800000000000000000000006044820152fd5b15612f6f57565b606460405162461bcd60e51b815260206004820152601160248201527f4d69736d617463686564206172726179730000000000000000000000000000006044820152fd5b90156119185790565b91908110156119185760051b0190565b35610c6b816103e0565b15612fdd57565b606460405162461bcd60e51b815260206004820152601460248201527f416d6f756e742065786365656473206c696d69740000000000000000000000006044820152fd5b91908110156119185760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561035657019081359167ffffffffffffffff8311610356576020018236038113610356579190565b1561308857565b606460405162461bcd60e51b815260206004820152600f60248201527f4173736574206e6f7420666f756e6400000000000000000000000000000000006044820152fd5b604051906130db6040836105bc565b600682527f524f5554455200000000000000000000000000000000000000000000000000006020830152565b604051906131166040836105bc565b600582527f544f4b454e0000000000000000000000000000000000000000000000000000006020830152565b610c6b93926060928252151560208201528160408201520190610ba5565b1561316757565b606460405162461bcd60e51b815260206004820152601560248201527f496e76616c696420746f6b656e206164647265737300000000000000000000006044820152fd5b156131b257565b606460405162461bcd60e51b815260206004820152601460248201527f546f6b656e20616c7265616479206578697374730000000000000000000000006044820152fd5b156131fd57565b606460405162461bcd60e51b815260206004820152601a60248201527f496e73756666696369656e7420746f6b656e2062616c616e63650000000000006044820152fd5b1561324857565b606460405162461bcd60e51b815260206004820152601860248201527f496e73756666696369656e74204554482062616c616e636500000000000000006044820152fd5b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16156132c557565b63e2517d3f60e01b60005233600452600060245260446000fd5b3360009081527fee57cd81e84075558e8fcc182a1f4393f91fc97f963a136e66b7f949a62f319f602052604090205460ff161561331857565b63e2517d3f60e01b600052336004527f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92960245260446000fd5b80600052600060205260ff61337d336040600020906001600160a01b0316600052602052604060002090565b5416156133875750565b63e2517d3f60e01b6000523360045260245260446000fd5b6002600154146133b0576002600155565b7f3ee5aeb50000000000000000000000000000000000000000000000000000000060005260046000fd5b60ff600254166133e657565b7fd93c06650000000000000000000000000000000000000000000000000000000060005260046000fd5b600c5460018101809111611e56576040516080810181811067ffffffffffffffff8211176105df57829160609160405260018152426020820152336040820152015260ff196009541660ff60011515161760095542600a55613495336001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19600b541617600b55565b600c55565b156134a157565b606460405162461bcd60e51b815260206004820152601360248201527f496e76616c69642064617461206c656e677468000000000000000000000000006044820152fd5b156134ec57565b606460405162461bcd60e51b815260206004820152601960248201527f496e76616c69642066756e6374696f6e2073656c6563746f72000000000000006044820152fd5b51906105f3826103e0565b9160a08383031261035657825192602081015192604082015167ffffffffffffffff81116103565782019080601f830112156103565781519167ffffffffffffffff83116105df578260051b906040519361359960208401866105bc565b845260208085019282010192831161035657602001905b8282106135cf575050509160806135c960608401613530565b92015190565b6020809183516135de816103e0565b8152019101906135b0565b156135f057565b606460405162461bcd60e51b815260206004820152601360248201527f496e76616c69642070617468206c656e677468000000000000000000000000006044820152fd5b8051156119185760200190565b80518210156119185760209160051b010190565b1561365c57565b606460405162461bcd60e51b815260206004820152600c60248201527f496e76616c6964207061746800000000000000000000000000000000000000006044820152fd5b156136a757565b606460405162461bcd60e51b815260206004820152601160248201527f496e76616c696420726563697069656e740000000000000000000000000000006044820152fd5b156136f257565b606460405162461bcd60e51b815260206004820152600e60248201527f57726f6e6720616d6f756e74496e0000000000000000000000000000000000006044820152fd5b1561373d57565b606460405162461bcd60e51b815260206004820152601060248201527f4578706972656420646561646c696e65000000000000000000000000000000006044820152fd5b1561378857565b606460405162461bcd60e51b815260206004820152601660248201527f496e73756666696369656e74206d696e52657475726e000000000000000000006044820152fd5b9092916137dd60048451101561349a565b6338ed173960e01b6001600160e01b0319602085015161381c61381761047c836001600160e01b0319166000526010602052604060002090565b6134e5565b1614613829575b50505050565b6138c4936138b76138bd9361385d61384e876138486138a79951612716565b90613ff8565b6020808251830101910161353b565b999396919250936138726002845110156135e9565b6001600160a01b038061389461388786613634565b516001600160a01b031690565b921691161491826138cd575b5050613655565b6001600160a01b031630146136a0565b146136eb565b4210613736565b38808080613823565b6001600160a01b039192506138f0613887826138ea859451612707565b90613641565b921691161438806138a0565b909361390c60048251101561349a565b6338ed173960e01b6001600160e01b0319602083015161394661381761047c836001600160e01b0319166000526010602052604060002090565b1614613954575b5050505050565b613987926138a7926138b761397361384e856138486138bd9751612716565b98929b9093956138726002845110156135e9565b80613995575b80808061394d565b6139a0911015613781565b388061398d565b60009182916020825192019034905af16139bf61298e565b50156139c757565b606460405162461bcd60e51b815260206004820152600b60248201527f53776170206661696c65640000000000000000000000000000000000000000006044820152fd5b6001600160a01b03811660009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd9602052604090205460ff16613ad9576001600160a01b031660008181527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd960205260408120805460ff191660011790553391907f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b50600090565b80600052600060205260ff613b0b836040600020906001600160a01b0316600052602052604060002090565b5416613b7c57806000526000602052613b3b826040600020906001600160a01b0316600052602052604060002090565b600160ff198254161790556001600160a01b03339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d600080a4600190565b5050600090565b6001600160a01b03811660009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd9602052604090205460ff1615613ad9576001600160a01b031660008181527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd960205260408120805460ff191690553391907f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b80600052600060205260ff613c7b836040600020906001600160a01b0316600052602052604060002090565b541615613b7c57806000526000602052613cac826040600020906001600160a01b0316600052602052604060002090565b60ff1981541690556001600160a01b03339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b600080a4600190565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000060208201526001600160a01b039290921660248301526044808301939093529181526105f391613d3f6064836105bc565b6140c1565b15613d4b57565b606460405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207377617020646174610000000000000000000000000000006044820152fd5b909160c082840312610356578151613da6816103e0565b926020830151613db5816103e0565b926040810151613dc4816103e0565b9260608201519260808301519260a08101519067ffffffffffffffff8211610356570181601f82011215610356578051613dfd816105f5565b92613e0b60405194856105bc565b8184526020828401011161035657610c6b9160208085019101610b82565b926001600160a01b039081610c6b9897948160c09895168752166020860152166040840152606083015260808201528160a08201520190610ba5565b91608093613e92916001600160a01b0393989796988552602085015260a0604085015260a0840190610c1d565b951660608201520152565b90613eac600483511015613d44565b60208201516001600160e01b031981166338ed173960e01b8103613f0557506104fe613ee361384e85613848610c6b969751612716565b935096916001600160a01b036040519889976020890152169260248701613e65565b7f12aa3caf000000000000000000000000000000000000000000000000000000008114908115613f8c575b50613f3a57505090565b6104fe613f61613f5285613848610c6b969751612716565b60208082518301019101613d8f565b94909391506001600160a01b03808060409b959b519b8c9a60208c0152169316911660248801613e29565b7f7c0252000000000000000000000000000000000000000000000000000000000091501438613f30565b90613fc0826105f5565b613fcd60405191826105bc565b828152601f19613fdd82946105f5565b0190602036910137565b908151811015611918570160200190565b91908251816004019081600411611e56571061407d5761401781613fb6565b9060005b818110614029575090925050565b8061406961404361403d6001946004612740565b88613fe7565b517fff000000000000000000000000000000000000000000000000000000000000001690565b60001a6140768286613fe7565b530161401b565b606460405162461bcd60e51b815260206004820152601960248201527f736c69636542797465733a206f7574206f6620626f756e6473000000000000006044820152fd5b906000602091828151910182855af11561269a576000513d61412957506001600160a01b0381163b155b6140f25750565b6001600160a01b03907f5274afe7000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b600114156140eb565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000060208083019182526001600160a01b03851660248401526044808401969096529482529293909260009061418b6064866105bc565b84519082855af1600051903d81614206575b501590505b6141ab57505050565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000060208201526001600160a01b039093166024840152600060448401526105f392613d3f9061420081606481016104fe565b826140c1565b1515905061422657506141a26001600160a01b0382163b15155b3861419d565b60016141a2911461422056fea264697066735822122092987bae63561ede8bb0b4c52a35f57ad63dfe43595b2c67a6cc9cc5bf91271064736f6c634300081a00332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0dc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd9ee57cd81e84075558e8fcc182a1f4393f91fc97f963a136e66b7f949a62f319fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5000000000000000000000000acd863bba801efe9c619f6547ecdc6c562c03f36000000000000000000000000acd863bba801efe9c619f6547ecdc6c562c03f36000000000000000000000000000000000000000000000000000000000098968000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000acd863bba801efe9c619f6547ecdc6c562c03f3600000000000000000000000057489ee6252a930900755033e0f0735577cd244700000000000000000000000019f4a92597b6570f5790d826caf5d32c4fbaef62
Deployed Bytecode
0x60806040526004361015610018575b361561001657005b005b60003560e01c806301ffc9a71461033a578063083518381461033557806308dc0334146103305780630e2b0c941461032b5780630ffb3058146103265780631ba64197146102f95780631faee24f1461032157806322428b671461031c578063248a9ca3146103175780632a5c792a146103125780632ee773b51461030d5780632f2ff15d1461030857806336568abe146103035780633b2fda74146102fe5780633d2fe2fe146102f95780633f4ba83a146102f4578063445b1e4b146102ef5780634bbc0915146102ea5780634c36f10d146102e55780635c975abb146102e0578063634282af146102db578063672dbf55146102d657806367fc22c6146102d15780636d1ea3fa146102cc5780636ff1c9bc146102c757806371e259ed146102c25780637579a804146102b85780637609d7f6146102bd57806377dc3429146102b857806379502c55146102b35780637e8db6b31461024f5780638456cb59146102ae57806384f51b15146102a957806386001519146102a4578063864e18271461029f5780638b5b10641461029a57806391d1485414610295578063a030a8db14610290578063a217fddf1461028b578063a5218fd814610286578063b150377414610281578063d1a645041461027c578063d547741f14610277578063da3e339714610272578063db341d8c1461026d578063e275c99714610268578063f3fef3a314610263578063f5b541a61461025e578063f975951814610259578063fac1b9bc146102545763fe4906f10361000e575b611861565b612129565b61210c565b6120d1565b612012565b611ff4565b611e7c565b611daf565b611d6c565b611c22565b611be7565b611b8d565b611b71565b611af0565b611a68565b6119e8565b6119a3565b611985565b611940565b61187d565b611807565b611762565b6117a2565b611505565b6113ea565b6113a7565b611232565b611212565b6111b8565b611195565b611174565b611131565b6110d0565b61104e565b610bca565b611004565b610fa1565b610f59565b610e1f565b610d9f565b610d6a565b610d10565b610c6e565b610a86565b610a43565b610648565b6103f1565b61035b565b600435906001600160e01b03198216820361035657565b600080fd5b346103565760206003193601126103565760206001600160e01b031961037f61033f565b167f7965db0b0000000000000000000000000000000000000000000000000000000081149081156103b6575b506040519015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386103ab565b6001600160a01b0381160361035657565b346103565760406003193601126103565760043561040e816103e0565b7f4542bd31a6cc3179d1a1b1f87bd081e653199f97da71c0110ea63a86851575686105a160243561043d61328c565b6105566001600160a01b03851694610456861515612292565b61048c61048761048361047c846001600160a01b03166000526014602052604060002090565b5460ff1690565b1590565b6122dd565b6104b96104ac826001600160a01b03166000526014602052604060002090565b600160ff19825416179055565b61055160185460405161050c816104fe6020820194856027917f524f555445525f00000000000000000000000000000000000000000000000000825260078201520190565b03601f1981018352826105bc565b5190206105176105e4565b8581526001602082015290601260408301525b606082015261054c836001600160a01b03166000526015602052604060002090565b612328565b612373565b6040519182918260a09181526001602082015260606040820152600660608201527f524f55544552000000000000000000000000000000000000000000000000000060808201520190565b0390a2005b634e487b7160e01b600052604160045260246000fd5b90601f601f19910116810190811067ffffffffffffffff8211176105df57604052565b6105a6565b604051906105f36080836105bc565b565b67ffffffffffffffff81116105df57601f01601f191660200190565b92919261061d826105f5565b9161062b60405193846105bc565b829481845281830111610356578281602093846000960137010152565b60c060031936011261035657600435610660816103e0565b60243561066c816103e0565b6044359160643561067c816103e0565b60843567ffffffffffffffff81116103565736602382011215610356576106ad903690602481600401359101610611565b3360009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd9602052604090205490949060a4359060ff1680610a2a575b6106f59061247e565b6106fd61339f565b6107056133da565b61071460ff60095416156124c9565b6001600160a01b0383169586600052601460205260ff6040600020541680610a0f575b61074090612514565b6001600160a01b0385169485600052601660205260ff60406000205416806109f4575b61076c9061255f565b8183856001600160a01b038a16998a600052601660205260ff60406000205416806109d9575b61079b9061255f565b6107a96005543a11156125aa565b811515806109ad575b6107bb906125f5565b6107e46107db8a6001600160a01b03166000526015602052604060002090565b54831115612640565b6107ec613410565b60088054901c60ff1661099a575b50506040516370a0823160e01b8152306004820152969250602091508690506024818a5afa94851561096e57600095610973575b5090610839916139a7565b6040516370a0823160e01b815230600482015292602084602481895afa91821561096e577f98afc1d8e92542e983ad90a2aa1fb90d691c207e0366b4f158970a6b9bc4d73e94600093610939575b50610894908310156126a6565b60009181811115610932576108a99250612725565b600354811015610919575b6108c76108c2600e5461274d565b600e55565b6040805192835260208301919091523390820152606090a461091060ff19600954166009556000600a5573ffffffffffffffffffffffffffffffffffffffff19600b5416600b55565b61001660018055565b61092d61092882600d54612740565b600d55565b6108b4565b50506108a9565b6108949193506109609060203d602011610967575b61095881836105bc565b81019061268b565b9290610887565b503d61094e565b61269a565b610839929195506109929060203d6020116109675761095881836105bc565b94909161082e565b6109a3946138fc565b38818385836107fa565b506107bb6109ce866001600160a01b03166000526015602052604060002090565b5483111590506107b2565b5060008b81526015602052604090206001015460ff16610792565b5060008681526015602052604090206001015460ff16610763565b5060008781526015602052604090206001015460ff16610737565b503360009081526013602052604090205460ff166106ec565b34610356576020600319360112610356576001600160a01b03600435610a68816103e0565b166000526013602052602060ff604060002054166040519015158152f35b3461035657600060031936011261035657602060405164012a05f2008152f35b90600182811c92168015610ad6575b6020831014610ac057565b634e487b7160e01b600052602260045260246000fd5b91607f1691610ab5565b9060405191826000825492610af484610aa6565b8084529360018116908115610b605750600114610b19575b506105f3925003836105bc565b90506000929192526020600020906000915b818310610b445750509060206105f39282010138610b0c565b6020919350806001915483858901015201910190918492610b2b565b602093506105f395925060ff1991501682840152151560051b82010138610b0c565b60005b838110610b955750506000910152565b8181015183820152602001610b85565b90601f19601f602093610bc381518092818752878088019101610b82565b0116010190565b34610356576020600319360112610356576001600160e01b0319610bec61033f565b166000526011602052610c19610c056040600020610ae0565b604051918291602083526020830190610ba5565b0390f35b906020808351928381520192019060005b818110610c3b5750505090565b82516001600160a01b0316845260209384019390920191600101610c2e565b906020610c6b928181520190610c1d565b90565b346103565760006003193601126103565760405180602060185491828152019060186000527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e9060005b818110610cdb57610c1985610ccf818703826105bc565b60405191829182610c5a565b82546001600160a01b0316845260209093019260019283019201610cb8565b634e487b7160e01b600052603260045260246000fd5b3461035657602060031936011261035657600435601754811015610356576001600160a01b0360209160176000527fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c15015416604051908152f35b34610356576020600319360112610356576020610d97600435600052600060205260016040600020015490565b604051908152f35b346103565760006003193601126103565760405180602060195491828152019060196000527f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c96959060005b818110610e0057610c1985610ccf818703826105bc565b82546001600160a01b0316845260209093019260019283019201610de9565b3461035657604060031936011261035657610e3861033f565b60243567ffffffffffffffff8111610356573660238201121561035657610e69903690602481600401359101610611565b610e7161328c565b6001600160e01b031982169182600052601060205260ff60406000205416610f15577f2cfb492f2352fd3565cc68739c0c593565d69c709db710d0757167b8c39e689b91610f0982610edd6104ac6105a1956001600160e01b0319166000526010602052604060002090565b610f0483610eff836001600160e01b0319166000526011602052604060002090565b6127b8565b612889565b604051918291826128b3565b606460405162461bcd60e51b815260206004820152601760248201527f53656c6563746f7220616c7265616479206578697374730000000000000000006044820152fd5b3461035657604060031936011261035657610016602435600435610f7c826103e0565b610f9c610f9782600052600060205260016040600020015490565b613351565b613adf565b3461035657604060031936011261035657600435602435610fc1816103e0565b336001600160a01b03821603610fda5761001691613c4f565b7f6697b2320000000000000000000000000000000000000000000000000000000060005260046000fd5b346103565760006003193601126103565761101d61328c565b61001660ff19600954166009556000600a5573ffffffffffffffffffffffffffffffffffffffff19600b5416600b55565b346103565760006003193601126103565761106761328c565b60025460ff8116156110a65760ff19166002557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b7f8dfc202b0000000000000000000000000000000000000000000000000000000060005260046000fd5b34610356576020600319360112610356576001600160a01b036004356110f5816103e0565b166000526014602052602060ff604060002054166040519015158152f35b60443590811515820361035657565b60243590811515820361035657565b34610356576020600319360112610356576004358015158091036103565761116f9061115b61328c565b6008805461ff00191691901b61ff00161790565b600855005b3461035657600060031936011261035657602060ff600f5416604051908152f35b3461035657600060031936011261035657602060ff600254166040519015158152f35b3461035657602060031936011261035657600435601954811015610356576001600160a01b0360209160196000527f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c9695015416604051908152f35b346103565760006003193601126103565760206040516402540be4008152f35b346103565760206003193601126103565761124b61033f565b61125361328c565b61127c61127761047c836001600160e01b0319166000526010602052604060002090565b6128cb565b6112a761129d826001600160e01b0319166000526010602052604060002090565b60ff198154169055565b6112cd6112c8826001600160e01b0319166000526011602052604060002090565b612916565b6001600160e01b03191660005b60125490818110156113a057826001600160e01b03196113096112fc846118d7565b90549060031b1c60e01b90565b16146113195760019150016112da565b6113396113336112fc61132e61135695612707565b6118d7565b916118d7565b90919063ffffffff83549160031b9260e01c831b921b1916179055565b61135e61294b565b7f2cfb492f2352fd3565cc68739c0c593565d69c709db710d0757167b8c39e689b604051806105a1816060906000815260406020820152600060408201520190565b505061135e565b34610356576020600319360112610356576001600160a01b036004356113cc816103e0565b166000526016602052602060ff604060002054166040519015158152f35b34610356576020600319360112610356576001600160a01b0360043561140f816103e0565b61141761328c565b1680611468574790611439600080808086335af161143361298e565b506129be565b60405191825233917e1a143d5b175701cb3246058ffac3d63945192075a926ff73a19930f09d587a90602090a3005b6040516370a0823160e01b815230600482015290602082602481845afa91821561096e576000926114a0575b50611439823383613cea565b6114ba91925060203d6020116109675761095881836105bc565b9038611494565b602060408183019282815284518094520192019060005b8181106114e55750505090565b82516001600160e01b0319168452602093840193909201916001016114d8565b3461035657600060031936011261035657604051601254808252906020810160126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444926000935b8160078601106116aa5791610c199484926115ac945491818110611686575b818110611667575b818110611648575b818110611629575b81811061160a575b8181106115eb575b8181106115cd575b106115b8575b5003826105bc565b604051918291826114c1565b6001600160e01b0319168152602001386115a4565b602083811b6001600160e01b0319168552909360019101930161159e565b604083901b6001600160e01b0319168452926001906020019301611596565b606083901b6001600160e01b031916845292600190602001930161158e565b608083901b6001600160e01b0319168452926001906020019301611586565b60a083901b6001600160e01b031916845292600190602001930161157e565b60c083901b6001600160e01b0319168452926001906020019301611576565b926020816116a26001938660e01b6001600160e01b0319169052565b01930161156e565b91600161010060089261175786546116ce838260e01b6001600160e01b0319169052565b60c081901b6001600160e01b031916602084015260a081901b6001600160e01b0319166040840152608081901b6001600160e01b0319166060840152606081901b6001600160e01b0319166080840152604081901b6001600160e01b03191660a0840152602081901b6001600160e01b03191660c08401526001600160e01b03191660e0830152565b01930194019361154f565b34610356576020600319360112610356576001600160e01b031961178461033f565b166000526010602052602060ff604060002054166040519015158152f35b34610356576020600319360112610356576001600160a01b036004356117c7816103e0565b1660005260156020526080604060002080549060ff60026001830154920154916040519384528181161515602085015260081c1660408301526060820152f35b346103565760006003193601126103565760e060035460ff60045460055460065460075491600854936040519687526020870152604086015260608501526080840152818116151560a084015260081c16151560c0820152f35b34610356576000600319360112610356576020604051600a8152f35b34610356576000600319360112610356576118966132df565b61189e6133da565b600160ff1960025416176002557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b90601254821015611918576012600052600382901c7fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444019160021b601c1690565b610cfa565b919091805483101561191857600052601c60206000208360031c019260021b1690565b3461035657602060031936011261035657600435601254811015610356576119696020916118d7565b90549060031b1c60e01b6001600160e01b031960405191168152f35b34610356576000600319360112610356576020600d54604051908152f35b3461035657600060031936011261035657608060ff60095416600a546001600160a01b03600b5416600c54916040519315158452602084015260408301526060820152f35b346103565760006003193601126103565760405180602060175491828152019060176000527fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c159060005b818110611a4957610c1985610ccf818703826105bc565b82546001600160a01b0316845260209093019260019283019201611a32565b3461035657604060031936011261035657602060ff611ab3602435600435611a8f826103e0565b600052600084526040600020906001600160a01b0316600052602052604060002090565b54166040519015158152f35b9181601f840112156103565782359167ffffffffffffffff8311610356576020808501948460051b01011161035657565b60a06003193601126103565760043567ffffffffffffffff811161035657611b1c903690600401611abf565b9060243560443567ffffffffffffffff811161035657611b40903690600401611abf565b606435949167ffffffffffffffff861161035657611b65610016963690600401611abf565b94909360843596612a09565b3461035657600060031936011261035657602060405160008152f35b3461035657602060031936011261035657600435601854811015610356576001600160a01b0360209160186000527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e015416604051908152f35b346103565760006003193601126103565760206040517f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b8152f35b3461035657606060031936011261035657600435611c3f816103e0565b7f4542bd31a6cc3179d1a1b1f87bd081e653199f97da71c0110ea63a8685157568602435611c6b611113565b90611c7461328c565b611d1561047c6001600160a01b0386169586600052601660205260ff604060002054168015611d41575b611ca790613081565b83611cc5826001600160a01b03166000526015602052604060002090565b55611cfc856001611ce9846001600160a01b03166000526015602052604060002090565b019060ff60ff1983541691151516179055565b6001600160a01b03166000526016602052604060002090565b15611d31576105a1611d25613107565b60405193849384613142565b6105a1611d3c6130cc565b611d25565b50611ca7611d6561047c836001600160a01b03166000526014602052604060002090565b9050611c9e565b3461035657604060031936011261035657610016602435600435611d8f826103e0565b611daa610f9782600052600060205260016040600020015490565b613c4f565b3461035657606060031936011261035657600435611dcc816103e0565b60243590611dd9826103e0565b6001600160a01b0360443591611ded6132df565b1691604051917fdd62ed3e0000000000000000000000000000000000000000000000000000000083523060048401526001600160a01b0382166024840152602083604481875afa92831561096e57600093611e5b575b508201809211611e565761001692614132565b6126f1565b611e7591935060203d6020116109675761095881836105bc565b9138611e43565b3461035657606060031936011261035657600435611e99816103e0565b6024356044359160ff83168303610356577f4542bd31a6cc3179d1a1b1f87bd081e653199f97da71c0110ea63a868515756891611fa96105a192611edb61328c565b611fa46001600160a01b03821696611ef4881515613160565b611f1f611f1a61048361047c866001600160a01b03166000526016602052604060002090565b6131ab565b611f3f6104ac846001600160a01b03166000526016602052604060002090565b601954604051611f81816104fe6020820194856026917f544f4b454e5f0000000000000000000000000000000000000000000000000000825260068201520190565b51902061052a611f8f6105e4565b878152600160208201529260ff166040840152565b6123cc565b6040519182918260a09181526001602082015260606040820152600560608201527f544f4b454e00000000000000000000000000000000000000000000000000000060808201520190565b34610356576000600319360112610356576020600e54604051908152f35b346103565760406003193601126103565760043561202f816103e0565b6001600160a01b036024359161204361328c565b16806120695761205582471015613241565b611439600080808086335af161143361298e565b6040516370a0823160e01b8152306004820152602081602481855afa90811561096e576120a29184916000916120b2575b5010156131f6565b6120ad823383613cea565b611439565b6120cb915060203d6020116109675761095881836105bc565b3861209a565b346103565760006003193601126103565760206040517f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9298152f35b346103565760006003193601126103565760206040516101f48152f35b3461035657604060031936011261035657600435612146816103e0565b7f1c6168ae13717a8cda4e1c9276a36c39333240268ba173a5a844201a8f4baa996001600160a01b03612177611122565b9261218061328c565b8380612248575b156121e65761219581613a0b565b5061219f81612425565b6121d2846121c0836001600160a01b03166000526013602052604060002090565b9060ff60ff1983541691151516179055565b6040519315158452169180602081016105a1565b831580612202575b1561219f576121fc81613b83565b5061219f565b506001600160a01b03811660009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd9602052604090206122439061047c565b6121ee565b506001600160a01b03811660009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd96020526040902061228d906104839061047c565b612187565b1561229957565b606460405162461bcd60e51b815260206004820152601660248201527f496e76616c696420726f757465722061646472657373000000000000000000006044820152fd5b156122e457565b606460405162461bcd60e51b815260206004820152601560248201527f526f7574657220616c72656164792065786973747300000000000000000000006044820152fd5b906060600291805184556001840161235360208301511515829060ff60ff1983541691151516179055565b6040820151815461ff00191660089190911b61ff00161790550151910155565b601854680100000000000000008110156105df57600181016018556000906018548110156119185760208260186001600160a01b0394522001911673ffffffffffffffffffffffffffffffffffffffff19825416179055565b601954680100000000000000008110156105df57600181016019556000906019548110156119185760208260196001600160a01b0394522001911673ffffffffffffffffffffffffffffffffffffffff19825416179055565b601754680100000000000000008110156105df57600181016017556000906017548110156119185760208260176001600160a01b0394522001911673ffffffffffffffffffffffffffffffffffffffff19825416179055565b1561248557565b606460405162461bcd60e51b815260206004820152600e60248201527f4e6f742061637469766520626f740000000000000000000000000000000000006044820152fd5b156124d057565b606460405162461bcd60e51b815260206004820152601160248201527f547261646520696e2070726f67726573730000000000000000000000000000006044820152fd5b1561251b57565b606460405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420726f757465720000000000000000000000000000000000006044820152fd5b1561256657565b606460405162461bcd60e51b815260206004820152600d60248201527f496e76616c696420746f6b656e000000000000000000000000000000000000006044820152fd5b156125b157565b606460405162461bcd60e51b815260206004820152601260248201527f47617320707269636520746f6f206869676800000000000000000000000000006044820152fd5b156125fc57565b606460405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420616d6f756e740000000000000000000000000000000000006044820152fd5b1561264757565b606460405162461bcd60e51b815260206004820152601460248201527f4578636565647320726f75746572206c696d69740000000000000000000000006044820152fd5b90816020910312610356575190565b6040513d6000823e3d90fd5b156126ad57565b606460405162461bcd60e51b815260206004820152601360248201527f496e73756666696369656e742072657475726e000000000000000000000000006044820152fd5b634e487b7160e01b600052601160045260246000fd5b906000198201918211611e5657565b906003198201918211611e5657565b91908203918211611e5657565b9060018201809211611e5657565b91908201809211611e5657565b6000198114611e565760010190565b818110612767575050565b6000815560010161275c565b9190601f811161278257505050565b6105f3926000526020600020906020601f840160051c830193106127ae575b601f0160051c019061275c565b90915081906127a1565b919091825167ffffffffffffffff81116105df576127e0816127da8454610aa6565b84612773565b6020601f8211600114612820578190612811939495600092612815575b50506000198260011b9260031b1c19161790565b9055565b0151905038806127fd565b601f1982169061283584600052602060002090565b9160005b81811061287157509583600195969710612858575b505050811b019055565b015160001960f88460031b161c1916905538808061284e565b9192602060018192868b015181550194019201612839565b60125490680100000000000000008210156105df576113398260016105f39401601255601261191d565b906040610c6b92600181528160208201520190610ba5565b156128d257565b606460405162461bcd60e51b815260206004820152601660248201527f53656c6563746f7220646f65736e2774206578697374000000000000000000006044820152fd5b6000906129238154610aa6565b601f811161292f575055565b8183526020832061294891601f0160051c81019061275c565b55565b6012548015612978576000190161296381601261191d565b63ffffffff82549160031b1b19169055601255565b634e487b7160e01b600052603160045260246000fd5b3d156129b9573d9061299f826105f5565b916129ad60405193846105bc565b82523d6000602084013e565b606090565b156129c557565b606460405162461bcd60e51b815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152fd5b3360009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd960205260409020549096919592949060ff1680612f04575b612a519061247e565b612a5961339f565b612a616133da565b612a7060ff60095416156124c9565b612a7e6005543a11156125aa565b600386101580612ef9575b612a9290612f1d565b612a9b86612707565b811480612ef0575b612aac90612f68565b612ae6612add612ac4612abf898b612fb3565b612fcc565b6001600160a01b03166000526015602052604060002090565b54861115612fd6565b60005b868110612e9f575060005b818110612e325750612b04613410565b612b23612b17612b17612abf898b612fb3565b6001600160a01b031690565b6040516370a0823160e01b81523060048201529490602090869060249082905afa94851561096e57600095612e11575b50859260005b838110612cde57505050505050612b79612b17612b17612abf8688612fb3565b6040516370a0823160e01b81523060048201529290602090849060249082905afa91821561096e57612c30612abf6001600160a01b0394612c609360009a7f98afc1d8e92542e983ad90a2aa1fb90d691c207e0366b4f158970a6b9bc4d73e988c93612cb9575b50612bed908310156126a6565b8a918181118c14612cb157612c029250612725565b965b600354881015612c9d575b612c1d6108c2600e5461274d565b612c2a612abf828b612fb3565b98612fb3565b9183604051948594169716953391849160409194936001600160a01b039160608501968552602085015216910152565b0390a4612c9460ff19600954166009556000600a5573ffffffffffffffffffffffffffffffffffffffff19600b5416600b55565b6105f360018055565b612cac61092889600d54612740565b612c0f565b505096612c04565b612bed919350612cd79060203d6020116109675761095881836105bc565b9290612be0565b89898783612d92575b8380938988612d4395612d1283612d0d612d068f999c8e60019e613021565b3691610611565b613e9d565b958694612d2560085460ff9060081c1690565b612d49575b50919050612abf9350612d3e949250612fbc565b6139a7565b01612b59565b86612d7f92612d79612abf84612d69612abf612d859d8a612abf99612fbc565b97612d7386612732565b91612fbc565b95612fbc565b506137cc565b8281898f8f8b8b92612d2a565b50829650612abf612daa93612b1792612b1794612fbc565b6040516370a0823160e01b81523060048201529490602090869060249082905afa94851561096e578285838d8a888f9b8497600091612df3575b509b9550509250935050612ce7565b612e0b915060203d81116109675761095881836105bc565b38612de4565b612e2b91955060203d6020116109675761095881836105bc565b9338612b53565b80612e6261047c612e49612abf600195878b612fbc565b6001600160a01b03166000526014602052604060002090565b80612e77575b612e7190612514565b01612af4565b50612e71612e9883612e90612ac4612abf86898d612fbc565b015460ff1690565b9050612e68565b80612ecb89828a612ebc61047c611cfc612abf6001998588612fbc565b9283612ed1575b50505061255f565b01612ae9565b612ee89350612abf8793612e9093612ac493612fbc565b828a8c612ec3565b50818114612aa3565b50600a861115612a89565b503360009081526013602052604090205460ff16612a48565b15612f2457565b606460405162461bcd60e51b815260206004820152601560248201527f496e76616c696420746f6b656e73206c656e67746800000000000000000000006044820152fd5b15612f6f57565b606460405162461bcd60e51b815260206004820152601160248201527f4d69736d617463686564206172726179730000000000000000000000000000006044820152fd5b90156119185790565b91908110156119185760051b0190565b35610c6b816103e0565b15612fdd57565b606460405162461bcd60e51b815260206004820152601460248201527f416d6f756e742065786365656473206c696d69740000000000000000000000006044820152fd5b91908110156119185760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561035657019081359167ffffffffffffffff8311610356576020018236038113610356579190565b1561308857565b606460405162461bcd60e51b815260206004820152600f60248201527f4173736574206e6f7420666f756e6400000000000000000000000000000000006044820152fd5b604051906130db6040836105bc565b600682527f524f5554455200000000000000000000000000000000000000000000000000006020830152565b604051906131166040836105bc565b600582527f544f4b454e0000000000000000000000000000000000000000000000000000006020830152565b610c6b93926060928252151560208201528160408201520190610ba5565b1561316757565b606460405162461bcd60e51b815260206004820152601560248201527f496e76616c696420746f6b656e206164647265737300000000000000000000006044820152fd5b156131b257565b606460405162461bcd60e51b815260206004820152601460248201527f546f6b656e20616c7265616479206578697374730000000000000000000000006044820152fd5b156131fd57565b606460405162461bcd60e51b815260206004820152601a60248201527f496e73756666696369656e7420746f6b656e2062616c616e63650000000000006044820152fd5b1561324857565b606460405162461bcd60e51b815260206004820152601860248201527f496e73756666696369656e74204554482062616c616e636500000000000000006044820152fd5b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16156132c557565b63e2517d3f60e01b60005233600452600060245260446000fd5b3360009081527fee57cd81e84075558e8fcc182a1f4393f91fc97f963a136e66b7f949a62f319f602052604090205460ff161561331857565b63e2517d3f60e01b600052336004527f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92960245260446000fd5b80600052600060205260ff61337d336040600020906001600160a01b0316600052602052604060002090565b5416156133875750565b63e2517d3f60e01b6000523360045260245260446000fd5b6002600154146133b0576002600155565b7f3ee5aeb50000000000000000000000000000000000000000000000000000000060005260046000fd5b60ff600254166133e657565b7fd93c06650000000000000000000000000000000000000000000000000000000060005260046000fd5b600c5460018101809111611e56576040516080810181811067ffffffffffffffff8211176105df57829160609160405260018152426020820152336040820152015260ff196009541660ff60011515161760095542600a55613495336001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19600b541617600b55565b600c55565b156134a157565b606460405162461bcd60e51b815260206004820152601360248201527f496e76616c69642064617461206c656e677468000000000000000000000000006044820152fd5b156134ec57565b606460405162461bcd60e51b815260206004820152601960248201527f496e76616c69642066756e6374696f6e2073656c6563746f72000000000000006044820152fd5b51906105f3826103e0565b9160a08383031261035657825192602081015192604082015167ffffffffffffffff81116103565782019080601f830112156103565781519167ffffffffffffffff83116105df578260051b906040519361359960208401866105bc565b845260208085019282010192831161035657602001905b8282106135cf575050509160806135c960608401613530565b92015190565b6020809183516135de816103e0565b8152019101906135b0565b156135f057565b606460405162461bcd60e51b815260206004820152601360248201527f496e76616c69642070617468206c656e677468000000000000000000000000006044820152fd5b8051156119185760200190565b80518210156119185760209160051b010190565b1561365c57565b606460405162461bcd60e51b815260206004820152600c60248201527f496e76616c6964207061746800000000000000000000000000000000000000006044820152fd5b156136a757565b606460405162461bcd60e51b815260206004820152601160248201527f496e76616c696420726563697069656e740000000000000000000000000000006044820152fd5b156136f257565b606460405162461bcd60e51b815260206004820152600e60248201527f57726f6e6720616d6f756e74496e0000000000000000000000000000000000006044820152fd5b1561373d57565b606460405162461bcd60e51b815260206004820152601060248201527f4578706972656420646561646c696e65000000000000000000000000000000006044820152fd5b1561378857565b606460405162461bcd60e51b815260206004820152601660248201527f496e73756666696369656e74206d696e52657475726e000000000000000000006044820152fd5b9092916137dd60048451101561349a565b6338ed173960e01b6001600160e01b0319602085015161381c61381761047c836001600160e01b0319166000526010602052604060002090565b6134e5565b1614613829575b50505050565b6138c4936138b76138bd9361385d61384e876138486138a79951612716565b90613ff8565b6020808251830101910161353b565b999396919250936138726002845110156135e9565b6001600160a01b038061389461388786613634565b516001600160a01b031690565b921691161491826138cd575b5050613655565b6001600160a01b031630146136a0565b146136eb565b4210613736565b38808080613823565b6001600160a01b039192506138f0613887826138ea859451612707565b90613641565b921691161438806138a0565b909361390c60048251101561349a565b6338ed173960e01b6001600160e01b0319602083015161394661381761047c836001600160e01b0319166000526010602052604060002090565b1614613954575b5050505050565b613987926138a7926138b761397361384e856138486138bd9751612716565b98929b9093956138726002845110156135e9565b80613995575b80808061394d565b6139a0911015613781565b388061398d565b60009182916020825192019034905af16139bf61298e565b50156139c757565b606460405162461bcd60e51b815260206004820152600b60248201527f53776170206661696c65640000000000000000000000000000000000000000006044820152fd5b6001600160a01b03811660009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd9602052604090205460ff16613ad9576001600160a01b031660008181527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd960205260408120805460ff191660011790553391907f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b50600090565b80600052600060205260ff613b0b836040600020906001600160a01b0316600052602052604060002090565b5416613b7c57806000526000602052613b3b826040600020906001600160a01b0316600052602052604060002090565b600160ff198254161790556001600160a01b03339216907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d600080a4600190565b5050600090565b6001600160a01b03811660009081527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd9602052604090205460ff1615613ad9576001600160a01b031660008181527fc748e564f3b67d777128c175b8f51af1229a55070ce08662ef69b06b4c56ecd960205260408120805460ff191690553391907f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b80600052600060205260ff613c7b836040600020906001600160a01b0316600052602052604060002090565b541615613b7c57806000526000602052613cac826040600020906001600160a01b0316600052602052604060002090565b60ff1981541690556001600160a01b03339216907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b600080a4600190565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000060208201526001600160a01b039290921660248301526044808301939093529181526105f391613d3f6064836105bc565b6140c1565b15613d4b57565b606460405162461bcd60e51b815260206004820152601160248201527f496e76616c6964207377617020646174610000000000000000000000000000006044820152fd5b909160c082840312610356578151613da6816103e0565b926020830151613db5816103e0565b926040810151613dc4816103e0565b9260608201519260808301519260a08101519067ffffffffffffffff8211610356570181601f82011215610356578051613dfd816105f5565b92613e0b60405194856105bc565b8184526020828401011161035657610c6b9160208085019101610b82565b926001600160a01b039081610c6b9897948160c09895168752166020860152166040840152606083015260808201528160a08201520190610ba5565b91608093613e92916001600160a01b0393989796988552602085015260a0604085015260a0840190610c1d565b951660608201520152565b90613eac600483511015613d44565b60208201516001600160e01b031981166338ed173960e01b8103613f0557506104fe613ee361384e85613848610c6b969751612716565b935096916001600160a01b036040519889976020890152169260248701613e65565b7f12aa3caf000000000000000000000000000000000000000000000000000000008114908115613f8c575b50613f3a57505090565b6104fe613f61613f5285613848610c6b969751612716565b60208082518301019101613d8f565b94909391506001600160a01b03808060409b959b519b8c9a60208c0152169316911660248801613e29565b7f7c0252000000000000000000000000000000000000000000000000000000000091501438613f30565b90613fc0826105f5565b613fcd60405191826105bc565b828152601f19613fdd82946105f5565b0190602036910137565b908151811015611918570160200190565b91908251816004019081600411611e56571061407d5761401781613fb6565b9060005b818110614029575090925050565b8061406961404361403d6001946004612740565b88613fe7565b517fff000000000000000000000000000000000000000000000000000000000000001690565b60001a6140768286613fe7565b530161401b565b606460405162461bcd60e51b815260206004820152601960248201527f736c69636542797465733a206f7574206f6620626f756e6473000000000000006044820152fd5b906000602091828151910182855af11561269a576000513d61412957506001600160a01b0381163b155b6140f25750565b6001600160a01b03907f5274afe7000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b600114156140eb565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000060208083019182526001600160a01b03851660248401526044808401969096529482529293909260009061418b6064866105bc565b84519082855af1600051903d81614206575b501590505b6141ab57505050565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000060208201526001600160a01b039093166024840152600060448401526105f392613d3f9061420081606481016104fe565b826140c1565b1515905061422657506141a26001600160a01b0382163b15155b3861419d565b60016141a2911461422056fea264697066735822122092987bae63561ede8bb0b4c52a35f57ad63dfe43595b2c67a6cc9cc5bf91271064736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000acd863bba801efe9c619f6547ecdc6c562c03f36000000000000000000000000acd863bba801efe9c619f6547ecdc6c562c03f36000000000000000000000000000000000000000000000000000000000098968000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000acd863bba801efe9c619f6547ecdc6c562c03f3600000000000000000000000057489ee6252a930900755033e0f0735577cd244700000000000000000000000019f4a92597b6570f5790d826caf5d32c4fbaef62
-----Decoded View---------------
Arg [0] : _admin (address): 0xacd863BBA801EFe9c619f6547eCdC6c562C03f36
Arg [1] : _operator (address): 0xacd863BBA801EFe9c619f6547eCdC6c562C03f36
Arg [2] : _minProfitThreshold (uint256): 10000000
Arg [3] : _botAddresses (address[]): 0xacd863BBA801EFe9c619f6547eCdC6c562C03f36,0x57489EE6252A930900755033e0F0735577Cd2447,0x19F4A92597B6570F5790D826CaF5d32c4fbaeF62
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000acd863bba801efe9c619f6547ecdc6c562c03f36
Arg [1] : 000000000000000000000000acd863bba801efe9c619f6547ecdc6c562c03f36
Arg [2] : 0000000000000000000000000000000000000000000000000000000000989680
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [5] : 000000000000000000000000acd863bba801efe9c619f6547ecdc6c562c03f36
Arg [6] : 00000000000000000000000057489ee6252a930900755033e0f0735577cd2447
Arg [7] : 00000000000000000000000019f4a92597b6570f5790d826caf5d32c4fbaef62
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.