Source Code
Latest 1 from a total of 1 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Set Min Fee | 18499221 | 870 days ago | IN | 0 ETH | 0.00085974 |
Latest 24 internal transactions
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Deposit | 23119117 | 224 days ago | 0.09685516 ETH | ||||
| Swap No Split Fr... | 23119117 | 224 days ago | 0.0978335 ETH | ||||
| Deposit | 23119109 | 224 days ago | 0.0099 ETH | ||||
| Swap No Split Fr... | 23119109 | 224 days ago | 0.01 ETH | ||||
| Transfer | 18643744 | 849 days ago | 0.00442101 ETH | ||||
| Transfer | 18643744 | 849 days ago | 0.00442101 ETH | ||||
| Deposit | 18643297 | 849 days ago | 0.01 ETH | ||||
| Swap No Split Fr... | 18643297 | 849 days ago | 0.01 ETH | ||||
| Deposit | 18634109 | 851 days ago | 0.015 ETH | ||||
| Swap No Split Fr... | 18634109 | 851 days ago | 0.015 ETH | ||||
| Transfer | 18632815 | 851 days ago | 0.0317742 ETH | ||||
| Transfer | 18632815 | 851 days ago | 0.0317742 ETH | ||||
| Deposit | 18632523 | 851 days ago | 0.01 ETH | ||||
| Swap No Split Fr... | 18632523 | 851 days ago | 0.01 ETH | ||||
| Deposit | 18612069 | 854 days ago | 0.01 ETH | ||||
| Swap No Split Fr... | 18612069 | 854 days ago | 0.01 ETH | ||||
| Deposit | 18608034 | 854 days ago | 0.01 ETH | ||||
| Swap No Split Fr... | 18608034 | 854 days ago | 0.01 ETH | ||||
| Deposit | 18607867 | 854 days ago | 0.01 ETH | ||||
| Swap No Split Fr... | 18607867 | 854 days ago | 0.01 ETH | ||||
| Deposit | 18590829 | 857 days ago | 0.025 ETH | ||||
| Swap No Split Fr... | 18590829 | 857 days ago | 0.025 ETH | ||||
| Transfer | 18499714 | 870 days ago | 0.0411055 ETH | ||||
| Transfer | 18499714 | 870 days ago | 0.0411055 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AvabotRouter
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
import "./interface/IAvabotRouter.sol";
import "./interface/IAdapter.sol";
import "./interface/IUniV2likeAdapter.sol";
import "./interface/IERC20.sol";
import "./interface/IWETH.sol";
import "./lib/SafeERC20.sol";
import "./lib/Maintainable.sol";
import "./lib/AvabotViewUtils.sol";
import "./lib/Recoverable.sol";
import "./lib/SafeERC20.sol";
import "./interface/IUniswapFactory.sol";
contract AvabotRouter is Maintainable, Recoverable, IAvabotRouter {
using SafeERC20 for IERC20;
using OfferUtils for Offer;
address public immutable WNATIVE;
address public constant NATIVE = address(0);
string public constant NAME = "AvabotRouter";
uint256 public constant FEE_DENOMINATOR = 1e4;
uint256 public MIN_FEE = 0;
address public FEE_CLAIMER;
address[] public TRUSTED_TOKENS;
address[] public ADAPTERS;
// Avabot
error TransferToZeroAddressAttempt();
error TokenTransferFailed(address token, address dest, uint256 amount);
error CallerIsNotFeeClaimer(address caller);
error TransactionTooOld();
event AvabotSwapFee(address indexed _token, address indexed _sender, string _referral, uint256 _feeAmount);
modifier onlyFeeClaimer() {
_checkFeeClaimer();
_;
}
modifier checkDeadline(uint256 deadline) {
_checkDeadline(deadline);
_;
}
function _checkFeeClaimer() internal view virtual {
address msgSender = _msgSender();
if (msgSender != FEE_CLAIMER) revert CallerIsNotFeeClaimer(msgSender);
}
function _checkDeadline(uint256 deadline) internal view virtual {
if (deadline < block.timestamp) revert TransactionTooOld();
}
constructor(
address[] memory _adapters,
address[] memory _trustedTokens,
address _feeClaimer,
address _wrapped_native
) {
setAllowanceForWrapping(_wrapped_native);
setTrustedTokens(_trustedTokens);
setFeeClaimer(_feeClaimer);
setAdapters(_adapters);
WNATIVE = _wrapped_native;
}
// -- SETTERS --
function setAllowanceForWrapping(address _wnative) public onlyMaintainer {
IERC20(_wnative).safeApprove(_wnative, type(uint256).max);
}
function setTrustedTokens(address[] memory _trustedTokens) public override onlyMaintainer {
emit UpdatedTrustedTokens(_trustedTokens);
TRUSTED_TOKENS = _trustedTokens;
}
function setAdapters(address[] memory _adapters) public override onlyMaintainer {
emit UpdatedAdapters(_adapters);
ADAPTERS = _adapters;
}
function setMinFee(uint256 _fee) external override onlyMaintainer {
emit UpdatedMinFee(MIN_FEE, _fee);
MIN_FEE = _fee;
}
function setFeeClaimer(address _claimer) public override onlyMaintainer {
emit UpdatedFeeClaimer(FEE_CLAIMER, _claimer);
FEE_CLAIMER = _claimer;
}
// -- GENERAL --
function trustedTokensCount() external view override returns (uint256) {
return TRUSTED_TOKENS.length;
}
function adaptersCount() external view override returns (uint256) {
return ADAPTERS.length;
}
// Fallback
receive() external payable {}
// -- HELPERS --
function _applyFee(uint256 _amountIn, uint256 _fee) internal view returns (uint256) {
require(_fee >= MIN_FEE, "AvabotRouter: Insufficient fee");
return (_amountIn * (FEE_DENOMINATOR - _fee)) / FEE_DENOMINATOR;
}
function _wrap(uint256 _amount) internal {
IWETH(WNATIVE).deposit{ value: _amount }();
}
function _unwrap(uint256 _amount) internal {
IWETH(WNATIVE).withdraw(_amount);
}
/**
* @notice Return tokens to user
* @dev Pass address(0) for ETH
* @param _token address
* @param _amount tokens to return
* @param _to address where funds should be sent to
*/
function _returnTokensTo(
address _token,
uint256 _amount,
address _to
) internal {
if (address(this) != _to) {
if (_token == NATIVE) {
payable(_to).transfer(_amount);
} else {
IERC20(_token).safeTransfer(_to, _amount);
}
}
}
function _transferFrom(
address token,
address _from,
address _to,
uint256 _amount
) internal {
if (_from != address(this)) IERC20(token).safeTransferFrom(_from, _to, _amount);
else IERC20(token).safeTransfer(_to, _amount);
}
// -- QUERIES --
/**
* Query single adapter
*/
function queryAdapter(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
uint8 _index
) external view override returns (uint256) {
IAdapter _adapter = IAdapter(ADAPTERS[_index]);
uint256 amountOut = _adapter.query(_amountIn, _tokenIn, _tokenOut);
return amountOut;
}
/**
* Query specified adapters
*/
function queryNoSplit(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
uint8[] calldata _options
) public view override returns (Query memory) {
Query memory bestQuery;
for (uint8 i; i < _options.length; i++) {
address _adapter = ADAPTERS[_options[i]];
uint256 amountOut = IAdapter(_adapter).query(_amountIn, _tokenIn, _tokenOut);
if (i == 0 || amountOut > bestQuery.amountOut) {
bestQuery = Query(_adapter, _tokenIn, _tokenOut, amountOut);
}
}
return bestQuery;
}
/**
* Query all adapters
*/
function queryNoSplit(
uint256 _amountIn,
address _tokenIn,
address _tokenOut
) public view override returns (Query memory) {
Query memory bestQuery;
for (uint8 i; i < ADAPTERS.length; i++) {
address _adapter = ADAPTERS[i];
uint256 amountOut = IAdapter(_adapter).query(_amountIn, _tokenIn, _tokenOut);
if (i == 0 || amountOut > bestQuery.amountOut) {
bestQuery = Query(_adapter, _tokenIn, _tokenOut, amountOut);
}
}
return bestQuery;
}
/**
* Return path with best returns between two tokens
* Takes gas-cost into account
*/
function findBestPathWithGas(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
uint256 _maxSteps,
uint256 _gasPrice
) external view override returns (FormattedOffer memory) {
require(_maxSteps > 0 && _maxSteps < 5, "AvabotRouter: Invalid max-steps");
Offer memory queries = OfferUtils.newOffer(_amountIn, _tokenIn);
uint256 gasPriceInExitTkn = _gasPrice > 0 ? getGasPriceInExitTkn(_gasPrice, _tokenOut) : 0;
queries = _findBestPath(_amountIn, _tokenIn, _tokenOut, _maxSteps, queries, gasPriceInExitTkn);
if (queries.adapters.length == 0) {
queries.amounts = "";
queries.path = "";
}
return queries.format();
}
// Find the market price between gas-asset(native) and token-out and express gas price in token-out
function getGasPriceInExitTkn(uint256 _gasPrice, address _tokenOut) internal view returns (uint256 price) {
// Avoid low-liquidity price appreciation (https://github.com/yieldyak/yak-aggregator/issues/20)
FormattedOffer memory gasQuery = findBestPath(1e18, WNATIVE, _tokenOut, 2);
if (gasQuery.path.length != 0) {
// Leave result in nWei to preserve precision for assets with low decimal places
price = (gasQuery.amounts[gasQuery.amounts.length - 1] * _gasPrice) / 1e9;
}
}
/**
* Return path with best returns between two tokens
*/
function findBestPath(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
uint256 _maxSteps
) public view override returns (FormattedOffer memory) {
require(_maxSteps > 0 && _maxSteps < 5, "AvabotRouter: Invalid max-steps");
Offer memory queries = OfferUtils.newOffer(_amountIn, _tokenIn);
queries = _findBestPath(_amountIn, _tokenIn, _tokenOut, _maxSteps, queries, 0);
// If no paths are found return empty struct
if (queries.adapters.length == 0) {
queries.amounts = "";
queries.path = "";
}
return queries.format();
}
function _findBestPath(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
uint256 _maxSteps,
Offer memory _queries,
uint256 _tknOutPriceNwei
) internal view returns (Offer memory) {
Offer memory bestOption = _queries.clone();
uint256 bestAmountOut;
uint256 gasEstimate;
bool withGas = _tknOutPriceNwei != 0;
// First check if there is a path directly from tokenIn to tokenOut
Query memory queryDirect = queryNoSplit(_amountIn, _tokenIn, _tokenOut);
if (queryDirect.amountOut != 0) {
if (withGas) {
gasEstimate = IAdapter(queryDirect.adapter).swapGasEstimate();
}
bestOption.addToTail(queryDirect.amountOut, queryDirect.adapter, queryDirect.tokenOut, gasEstimate);
bestAmountOut = queryDirect.amountOut;
}
// Only check the rest if they would go beyond step limit (Need at least 2 more steps)
if (_maxSteps > 1 && _queries.adapters.length / 32 <= _maxSteps - 2) {
// Check for paths that pass through trusted tokens
for (uint256 i = 0; i < TRUSTED_TOKENS.length; i++) {
if (_tokenIn == TRUSTED_TOKENS[i]) {
continue;
}
// Loop through all adapters to find the best one for swapping tokenIn for one of the trusted tokens
Query memory bestSwap = queryNoSplit(_amountIn, _tokenIn, TRUSTED_TOKENS[i]);
if (bestSwap.amountOut == 0) {
continue;
}
// Explore options that connect the current path to the tokenOut
Offer memory newOffer = _queries.clone();
if (withGas) {
gasEstimate = IAdapter(bestSwap.adapter).swapGasEstimate();
}
newOffer.addToTail(bestSwap.amountOut, bestSwap.adapter, bestSwap.tokenOut, gasEstimate);
newOffer = _findBestPath(
bestSwap.amountOut,
TRUSTED_TOKENS[i],
_tokenOut,
_maxSteps,
newOffer,
_tknOutPriceNwei
); // Recursive step
address tokenOut = newOffer.getTokenOut();
uint256 amountOut = newOffer.getAmountOut();
// Check that the last token in the path is the tokenOut and update the new best option if neccesary
if (_tokenOut == tokenOut && amountOut > bestAmountOut) {
if (newOffer.gasEstimate > bestOption.gasEstimate) {
uint256 gasCostDiff = (_tknOutPriceNwei * (newOffer.gasEstimate - bestOption.gasEstimate)) /
1e9;
uint256 priceDiff = amountOut - bestAmountOut;
if (gasCostDiff > priceDiff) {
continue;
}
}
bestAmountOut = amountOut;
bestOption = newOffer;
}
}
}
return bestOption;
}
// -- SWAPPERS --
// Avabot: fee on transfer default, only fee on transfer adapter
function _swapNoSplit(
Trade calldata _trade,
address _from,
address _to,
uint256 _fee,
uint256 _deadline,
string memory _referral
) internal checkDeadline(_deadline) returns (uint256) {
{
uint256 totalAmountIn;
if (_fee > 0 || MIN_FEE > 0) {
if (_trade.path[_trade.path.length - 1] != WNATIVE) {
totalAmountIn = _applyFee(_trade.amountIn, _fee);
emit AvabotSwapFee(_trade.path[0], msg.sender, _referral, _trade.amountIn - totalAmountIn);
} else {
totalAmountIn = _trade.amountIn;
}
} else {
totalAmountIn = _trade.amountIn;
}
if(IAdapter(_trade.adapters[0]).isUniV2like()) {
address factory = IUniV2likeAdapter(_trade.adapters[0]).factory();
_transferFrom(_trade.path[0], _from, IUniswapFactory(factory).getPair(_trade.path[0], _trade.path[1]), totalAmountIn);
} else {
_transferFrom(_trade.path[0], _from, _trade.adapters[0], totalAmountIn);
}
}
uint256[] memory amounts = new uint256[](2);
// stack too deep explain
// amounts[0]: _toBalance
// amounts[1]: _swapAmount
for (uint256 i = 0; i < _trade.adapters.length; i++) {
// All adapters should transfer output token to the following target
// All targets are the adapters, expect for the last swap where tokens are sent out
address targetAddress;
if (_trade.path[_trade.path.length - 1] == WNATIVE) {
targetAddress = i < _trade.adapters.length - 1 ? _trade.adapters[i + 1] : address(this);
} else {
targetAddress = i < _trade.adapters.length - 1 ? _trade.adapters[i + 1] : _to;
}
amounts[0] = IERC20(_trade.path[i + 1]).balanceOf(targetAddress);
IAdapter(_trade.adapters[i]).swap(0, 0, _trade.path[i], _trade.path[i + 1], targetAddress);
if (i == _trade.adapters.length - 1) {
uint256 diff = IERC20(_trade.path[i + 1]).balanceOf(targetAddress) - amounts[0];
require(diff >= _trade.amountOut, "AvabotRouter: Insufficient output amount");
amounts[1] = diff;
}
}
uint256 totalAmountOut;
if (_fee > 0 || MIN_FEE > 0) {
if (_trade.path[_trade.path.length - 1] == WNATIVE) {
totalAmountOut = _applyFee(amounts[1], _fee);
require(totalAmountOut >= _trade.amountOut, "AvabotRouter: Insufficient output amount");
emit AvabotSwapFee(
_trade.path[_trade.path.length - 1],
msg.sender,
_referral,
amounts[1] - totalAmountOut
);
} else {
totalAmountOut = amounts[1];
}
} else {
totalAmountOut = amounts[1];
}
if (_trade.path[_trade.path.length - 1] == WNATIVE && _to != address(this)) {
IERC20(_trade.path[_trade.path.length - 1]).safeTransfer(_to, totalAmountOut);
}
emit AvabotSwap(
_trade.path[0],
_trade.path[_trade.path.length - 1],
_trade.amountIn,
totalAmountOut,
msg.sender,
_fee
);
return totalAmountOut;
}
function swapNoSplit(
Trade calldata _trade,
uint256 _fee,
uint256 _deadline,
string calldata _referral
) public override {
_swapNoSplit(_trade, msg.sender, msg.sender, _fee, _deadline, _referral);
}
function swapNoSplitFromETH(
Trade calldata _trade,
uint256 _fee,
uint256 _deadline,
string calldata _referral
) external payable override {
require(_trade.path[0] == WNATIVE, "AvabotRouter: Path needs to begin with WETH");
_wrap(_trade.amountIn);
_swapNoSplit(_trade, address(this), msg.sender, _fee, _deadline, _referral);
}
function swapNoSplitToETH(
Trade calldata _trade,
uint256 _fee,
uint256 _deadline,
string calldata _referral
) public override {
require(_trade.path[_trade.path.length - 1] == WNATIVE, "AvabotRouter: Path needs to end with WETH");
uint256 returnAmount = _swapNoSplit(_trade, msg.sender, address(this), _fee, _deadline, _referral);
_unwrap(returnAmount);
_returnTokensTo(NATIVE, returnAmount, msg.sender);
}
/**
* Swap token to token without the need to approve the first token
*/
function swapNoSplitWithPermit(
Trade calldata _trade,
uint256 _fee,
uint256 _deadline,
string calldata _referral,
uint8 _v,
bytes32 _r,
bytes32 _s
) external override {
IERC20(_trade.path[0]).permit(msg.sender, address(this), _trade.amountIn, _deadline, _v, _r, _s);
swapNoSplit(_trade, _fee, _deadline, _referral);
}
/**
* Swap token to ETH without the need to approve the first token
*/
function swapNoSplitToETHWithPermit(
Trade calldata _trade,
uint256 _fee,
uint256 _deadline,
string calldata _referral,
uint8 _v,
bytes32 _r,
bytes32 _s
) external override {
IERC20(_trade.path[0]).permit(msg.sender, address(this), _trade.amountIn, _deadline, _v, _r, _s);
swapNoSplitToETH(_trade, _fee, _deadline, _referral);
}
// Avabot
/**
* @dev Utility method to be able to transfer native tokens out of Smart Account
* @notice only owner/ signatory of Smart Account with enough gas to spend can call this method
* @notice While enabling multisig module and renouncing ownership this will not work
* @param _dest Destination address
* @param _amount Amount of native tokens
*/
function transfer(address payable _dest, uint256 _amount) external onlyFeeClaimer {
if (_dest == address(0)) revert TransferToZeroAddressAttempt();
bool success;
assembly {
success := call(gas(), _dest, _amount, 0, 0, 0, 0)
}
if (!success) revert TokenTransferFailed(address(0), _dest, _amount);
}
/**
* @dev Utility method to be able to transfer ERC20 tokens out of Smart Account
* @notice only owner/ signatory of Smart Account with enough gas to spend can call this method
* @notice While enabling multisig module and renouncing ownership this will not work
* @param _token Token address
* @param _dest Destination/ Receiver address
* @param _amount Amount of tokens
*/
function pullTokens(
address _token,
address _dest,
uint256 _amount
) external onlyFeeClaimer {
if (_dest == address(0)) revert TransferToZeroAddressAttempt();
IERC20(_token).safeTransfer(_dest, _amount);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../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:
*
* ```
* 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}:
*
* ```
* 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.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
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 override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @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 override 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 override 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 override 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 `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @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 Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @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 signaling this.
*
* _Available since v3.1._
*/
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, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
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 `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 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);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* 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[EIP 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 v4.7.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IAdapter {
function isUniV2like() external view returns (bool);
function name() external view returns (string memory);
function swapGasEstimate() external view returns (uint256);
function swap(
uint256,
uint256,
address,
address,
address
) external;
function query(
uint256,
address,
address
) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
struct Query {
address adapter;
address tokenIn;
address tokenOut;
uint256 amountOut;
}
struct Offer {
bytes amounts;
bytes adapters;
bytes path;
uint256 gasEstimate;
}
struct FormattedOffer {
uint256[] amounts;
address[] adapters;
address[] path;
uint256 gasEstimate;
}
struct Trade {
uint256 amountIn;
uint256 amountOut;
address[] path;
address[] adapters;
}
interface IAvabotRouter {
event UpdatedTrustedTokens(address[] _newTrustedTokens);
event UpdatedAdapters(address[] _newAdapters);
event UpdatedMinFee(uint256 _oldMinFee, uint256 _newMinFee);
event UpdatedFeeClaimer(address _oldFeeClaimer, address _newFeeClaimer);
event AvabotSwap(address indexed _tokenIn, address indexed _tokenOut, uint256 _amountIn, uint256 _amountOut, address sender, uint256 _fee);
// admin
function setTrustedTokens(address[] memory _trustedTokens) external;
function setAdapters(address[] memory _adapters) external;
function setFeeClaimer(address _claimer) external;
function setMinFee(uint256 _fee) external;
// misc
function trustedTokensCount() external view returns (uint256);
function adaptersCount() external view returns (uint256);
// query
function queryAdapter(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
uint8 _index
) external returns (uint256);
function queryNoSplit(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
uint8[] calldata _options
) external view returns (Query memory);
function queryNoSplit(
uint256 _amountIn,
address _tokenIn,
address _tokenOut
) external view returns (Query memory);
function findBestPathWithGas(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
uint256 _maxSteps,
uint256 _gasPrice
) external view returns (FormattedOffer memory);
function findBestPath(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
uint256 _maxSteps
) external view returns (FormattedOffer memory);
// swap
function swapNoSplit(
Trade calldata _trade,
uint256 _fee,
uint256 _deadline,
string calldata referal
) external;
function swapNoSplitFromETH(
Trade calldata _trade,
uint256 _fee,
uint256 _deadline,
string calldata referal
) external payable;
function swapNoSplitToETH(
Trade calldata _trade,
uint256 _fee,
uint256 _deadline,
string calldata referal
) external;
function swapNoSplitWithPermit(
Trade calldata _trade,
uint256 _fee,
uint256 _deadline,
string calldata referal,
uint8 _v,
bytes32 _r,
bytes32 _s
) external;
function swapNoSplitToETHWithPermit(
Trade calldata _trade,
uint256 _fee,
uint256 _deadline,
string calldata referal,
uint8 _v,
bytes32 _r,
bytes32 _s
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
event Approval(address, address, uint256);
event Transfer(address, address, uint256);
function name() external view returns (string memory);
function decimals() external view returns (uint8);
function transferFrom(
address,
address,
uint256
) external returns (bool);
function allowance(address, address) external view returns (uint256);
function approve(address, uint256) external returns (bool);
function transfer(address, uint256) external returns (bool);
function balanceOf(address) external view returns (uint256);
function nonces(address) external view returns (uint256); // Only tokens that support permit
function permit(
address,
address,
uint256,
uint256,
uint8,
bytes32,
bytes32
) external; // Only tokens that support permit
function swap(address, uint256) external; // Only Avalanche bridge tokens
function swapSupply(address) external view returns (uint256); // Only Avalanche bridge tokens
function totalSupply() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IUniswapFactory {
function getPair(address tokenA, address tokenB) external view returns (address pair);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IAdapter.sol";
interface IUniV2likeAdapter is IAdapter {
function factory() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
interface IWETH is IERC20 {
function withdraw(uint256 amount) external;
function deposit() external payable;
}// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.4;
import { Offer, FormattedOffer } from "../interface/IAvabotRouter.sol";
import "./TypeConversion.sol";
library OfferUtils {
using TypeConversion for address;
using TypeConversion for uint256;
using TypeConversion for bytes;
function newOffer(
uint _amountIn,
address _tokenIn
) internal pure returns (Offer memory offer) {
offer.amounts = _amountIn.toBytes();
offer.path = _tokenIn.toBytes();
}
/**
* Makes a deep copy of Offer struct
*/
function clone(Offer memory _queries) internal pure returns (Offer memory) {
return Offer(_queries.amounts, _queries.adapters, _queries.path, _queries.gasEstimate);
}
/**
* Appends new elements to the end of Offer struct
*/
function addToTail(
Offer memory _queries,
uint256 _amount,
address _adapter,
address _tokenOut,
uint256 _gasEstimate
) internal pure {
_queries.path = bytes.concat(_queries.path, _tokenOut.toBytes());
_queries.adapters = bytes.concat(_queries.adapters, _adapter.toBytes());
_queries.amounts = bytes.concat(_queries.amounts, _amount.toBytes());
_queries.gasEstimate += _gasEstimate;
}
/**
* Formats elements in the Offer object from byte-arrays to integers and addresses
*/
function format(Offer memory _queries) internal pure returns (FormattedOffer memory) {
return
FormattedOffer(
_queries.amounts.toUints(),
_queries.adapters.toAddresses(),
_queries.path.toAddresses(),
_queries.gasEstimate
);
}
function getTokenOut(
Offer memory _offer
) internal pure returns (address tokenOut) {
tokenOut = _offer.path.toAddress(_offer.path.length); // Last 32 bytes
}
function getAmountOut(
Offer memory _offer
) internal pure returns (uint amountOut) {
amountOut = _offer.amounts.toUint(_offer.path.length); // Last 32 bytes
}
}
library FormattedOfferUtils {
using TypeConversion for address;
using TypeConversion for uint256;
using TypeConversion for bytes;
/**
* Appends new elements to the end of FormattedOffer
*/
function addToTail(
FormattedOffer memory offer,
uint256 amountOut,
address wrapper,
address tokenOut,
uint256 gasEstimate
) internal pure {
offer.amounts = bytes.concat(abi.encodePacked(offer.amounts), amountOut.toBytes()).toUints();
offer.adapters = bytes.concat(abi.encodePacked(offer.adapters), wrapper.toBytes()).toAddresses();
offer.path = bytes.concat(abi.encodePacked(offer.path), tokenOut.toBytes()).toAddresses();
offer.gasEstimate += gasEstimate;
}
/**
* Appends new elements to the beginning of FormattedOffer
*/
function addToHead(
FormattedOffer memory offer,
uint256 amountOut,
address wrapper,
address tokenOut,
uint256 gasEstimate
) internal pure {
offer.amounts = bytes.concat(amountOut.toBytes(), abi.encodePacked(offer.amounts)).toUints();
offer.adapters = bytes.concat(wrapper.toBytes(), abi.encodePacked(offer.adapters)).toAddresses();
offer.path = bytes.concat(tokenOut.toBytes(), abi.encodePacked(offer.path)).toAddresses();
offer.gasEstimate += gasEstimate;
}
function getAmountOut(FormattedOffer memory offer) internal pure returns (uint256) {
return offer.amounts[offer.amounts.length - 1];
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
/**
* @dev Contract module which extends the basic access control mechanism of Ownable
* to include many maintainers, whom only the owner (DEFAULT_ADMIN_ROLE) may add and
* remove.
*
* By default, the owner account will be the one that deploys the contract. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available this modifier:
* `onlyMaintainer`, which can be applied to your functions to restrict their use to
* the accounts with the role of maintainer.
*/
abstract contract Maintainable is Context, AccessControl {
bytes32 public constant MAINTAINER_ROLE = keccak256("MAINTAINER_ROLE");
constructor() {
address msgSender = _msgSender();
// members of the DEFAULT_ADMIN_ROLE alone may revoke and grant role membership
_setupRole(DEFAULT_ADMIN_ROLE, msgSender);
_setupRole(MAINTAINER_ROLE, msgSender);
}
function addMaintainer(address addedMaintainer) public virtual {
grantRole(MAINTAINER_ROLE, addedMaintainer);
}
function removeMaintainer(address removedMaintainer) public virtual {
revokeRole(MAINTAINER_ROLE, removedMaintainer);
}
function renounceRole(bytes32 role) public virtual {
address msgSender = _msgSender();
renounceRole(role, msgSender);
}
function transferOwnership(address newOwner) public virtual {
address msgSender = _msgSender();
grantRole(DEFAULT_ADMIN_ROLE, newOwner);
renounceRole(DEFAULT_ADMIN_ROLE, msgSender);
}
modifier onlyMaintainer() {
address msgSender = _msgSender();
require(hasRole(MAINTAINER_ROLE, msgSender), "Maintainable: Caller is not a maintainer");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import "./SafeERC20.sol";
import "./Maintainable.sol";
abstract contract Recoverable is Maintainable {
using SafeERC20 for IERC20;
event Recovered(
address indexed _asset,
uint amount
);
/**
* @notice Recover ERC20 from contract
* @param _tokenAddress token address
* @param _tokenAmount amount to recover
*/
function recoverERC20(address _tokenAddress, uint _tokenAmount) external onlyMaintainer {
require(_tokenAmount > 0, "Nothing to recover");
IERC20(_tokenAddress).safeTransfer(msg.sender, _tokenAmount);
emit Recovered(_tokenAddress, _tokenAmount);
}
/**
* @notice Recover native asset from contract
* @param _amount amount
*/
function recoverNative(uint _amount) external onlyMaintainer {
require(_amount > 0, "Nothing to recover");
payable(msg.sender).transfer(_amount);
emit Recovered(address(0), _amount);
}
}// This is a simplified version of OpenZepplin's SafeERC20 library
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
import "../interface/IERC20.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 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 ERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @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).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
library TypeConversion {
function toBytes12(address x) internal pure returns (bytes12 y) {
assembly { y := x }
}
function toBytes32(address x) internal pure returns (bytes32 y) {
assembly { y := x }
}
function toAddress(bytes32 x) internal pure returns (address y) {
assembly { y := x }
}
function toBytes(address x) internal pure returns (bytes memory y) {
y = new bytes(32);
assembly { mstore(add(y, 32), x) }
}
function toBytes(bytes32 x) internal pure returns (bytes memory y) {
y = new bytes(32);
assembly { mstore(add(y, 32), x) }
}
function toBytes(uint x) internal pure returns (bytes memory y) {
y = new bytes(32);
assembly { mstore(add(y, 32), x) }
}
function toAddress(
bytes memory x,
uint offset
) internal pure returns (address y) {
assembly { y := mload(add(x, offset)) }
}
function toUint(
bytes memory x,
uint offset
) internal pure returns (uint y) {
assembly { y := mload(add(x, offset)) }
}
function toBytes12(
bytes memory x,
uint offset
) internal pure returns (bytes12 y) {
assembly { y := mload(add(x, offset)) }
}
function toBytes32(
bytes memory x,
uint offset
) internal pure returns (bytes32 y) {
assembly { y := mload(add(x, offset)) }
}
function toAddresses(
bytes memory xs
) internal pure returns (address[] memory ys) {
ys = new address[](xs.length/32);
for (uint i=0; i < xs.length/32; i++) {
ys[i] = toAddress(xs, i*32 + 32);
}
}
function toUints(
bytes memory xs
) internal pure returns (uint[] memory ys) {
ys = new uint[](xs.length/32);
for (uint i=0; i < xs.length/32; i++) {
ys[i] = toUint(xs, i*32 + 32);
}
}
function toBytes32s(
bytes memory xs
) internal pure returns (bytes32[] memory ys) {
ys = new bytes32[](xs.length/32);
for (uint i=0; i < xs.length/32; i++) {
ys[i] = toBytes32(xs, i*32 + 32);
}
}
}{
"optimizer": {
"enabled": true,
"runs": 999
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address[]","name":"_adapters","type":"address[]"},{"internalType":"address[]","name":"_trustedTokens","type":"address[]"},{"internalType":"address","name":"_feeClaimer","type":"address"},{"internalType":"address","name":"_wrapped_native","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"CallerIsNotFeeClaimer","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"dest","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenTransferFailed","type":"error"},{"inputs":[],"name":"TransactionTooOld","type":"error"},{"inputs":[],"name":"TransferToZeroAddressAttempt","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":"_amountOut","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"AvabotSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"address","name":"_sender","type":"address"},{"indexed":false,"internalType":"string","name":"_referral","type":"string"},{"indexed":false,"internalType":"uint256","name":"_feeAmount","type":"uint256"}],"name":"AvabotSwapFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Recovered","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":false,"internalType":"address[]","name":"_newAdapters","type":"address[]"}],"name":"UpdatedAdapters","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_oldFeeClaimer","type":"address"},{"indexed":false,"internalType":"address","name":"_newFeeClaimer","type":"address"}],"name":"UpdatedFeeClaimer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_oldMinFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newMinFee","type":"uint256"}],"name":"UpdatedMinFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"_newTrustedTokens","type":"address[]"}],"name":"UpdatedTrustedTokens","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ADAPTERS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_CLAIMER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAINTAINER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NATIVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"TRUSTED_TOKENS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WNATIVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adaptersCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addedMaintainer","type":"address"}],"name":"addMaintainer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"uint256","name":"_maxSteps","type":"uint256"}],"name":"findBestPath","outputs":[{"components":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address[]","name":"adapters","type":"address[]"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"internalType":"struct FormattedOffer","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"uint256","name":"_maxSteps","type":"uint256"},{"internalType":"uint256","name":"_gasPrice","type":"uint256"}],"name":"findBestPathWithGas","outputs":[{"components":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address[]","name":"adapters","type":"address[]"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"internalType":"struct FormattedOffer","name":"","type":"tuple"}],"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":"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":"address","name":"_token","type":"address"},{"internalType":"address","name":"_dest","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"pullTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"uint8","name":"_index","type":"uint8"}],"name":"queryAdapter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"uint8[]","name":"_options","type":"uint8[]"}],"name":"queryNoSplit","outputs":[{"components":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"internalType":"struct Query","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"}],"name":"queryNoSplit","outputs":[{"components":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"internalType":"struct Query","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"removedMaintainer","type":"address"}],"name":"removeMaintainer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"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":"address[]","name":"_adapters","type":"address[]"}],"name":"setAdapters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wnative","type":"address"}],"name":"setAllowanceForWrapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_claimer","type":"address"}],"name":"setFeeClaimer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setMinFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_trustedTokens","type":"address[]"}],"name":"setTrustedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address[]","name":"adapters","type":"address[]"}],"internalType":"struct Trade","name":"_trade","type":"tuple"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"string","name":"_referral","type":"string"}],"name":"swapNoSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address[]","name":"adapters","type":"address[]"}],"internalType":"struct Trade","name":"_trade","type":"tuple"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"string","name":"_referral","type":"string"}],"name":"swapNoSplitFromETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address[]","name":"adapters","type":"address[]"}],"internalType":"struct Trade","name":"_trade","type":"tuple"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"string","name":"_referral","type":"string"}],"name":"swapNoSplitToETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address[]","name":"adapters","type":"address[]"}],"internalType":"struct Trade","name":"_trade","type":"tuple"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"string","name":"_referral","type":"string"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"swapNoSplitToETHWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address[]","name":"adapters","type":"address[]"}],"internalType":"struct Trade","name":"_trade","type":"tuple"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"string","name":"_referral","type":"string"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"swapNoSplitWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_dest","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"trustedTokensCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a060405260006001553480156200001657600080fd5b506040516200524c3803806200524c83398101604081905262000039916200083e565b3362000047600082620000ba565b620000737f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab9582620000ba565b506200007f81620000ca565b6200008a8362000164565b620000958262000226565b620000a084620002ff565b60601b6001600160601b03191660805250620009ad915050565b620000c68282620003bc565b5050565b3360008181526000805160206200520c833981519152602052604090205460ff166200013d5760405162461bcd60e51b815260206004820152602860248201526000805160206200522c83398151915260448201526734b73a30b4b732b960c11b60648201526084015b60405180910390fd5b620000c682600019846001600160a01b03166200045c60201b62001cd6179092919060201c565b3360008181526000805160206200520c833981519152602052604090205460ff16620001d35760405162461bcd60e51b815260206004820152602860248201526000805160206200522c83398151915260448201526734b73a30b4b732b960c11b606482015260840162000134565b7f658ff1688002926d8f426cb10c052ec29003f50042df9652d8613484c1a586478260405162000204919062000948565b60405180910390a1815162000221906003906020850190620006f0565b505050565b3360008181526000805160206200520c833981519152602052604090205460ff16620002955760405162461bcd60e51b815260206004820152602860248201526000805160206200522c83398151915260448201526734b73a30b4b732b960c11b606482015260840162000134565b600254604080516001600160a01b03928316815291841660208301527fb2c853ac4d80d18d058c43d8018d077a036e542a79acae1647f5ad2a8c76f4e2910160405180910390a150600280546001600160a01b0319166001600160a01b0392909216919091179055565b3360008181526000805160206200520c833981519152602052604090205460ff166200036e5760405162461bcd60e51b815260206004820152602860248201526000805160206200522c83398151915260448201526734b73a30b4b732b960c11b606482015260840162000134565b7febf7325f48e05e5e38809c69f8b02a7c907ed31d8768e6c2d841b1296a9225fe826040516200039f919062000948565b60405180910390a1815162000221906004906020850190620006f0565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620000c6576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620004183390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b801580620004ea5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015620004ad57600080fd5b505afa158015620004c2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004e89190620008f3565b155b6200055e5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606482015260840162000134565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b1790915262000221918591620005b616565b600080836001600160a01b031683604051620005d391906200090c565b6000604051808303816000865af19150503d806000811462000612576040519150601f19603f3d011682016040523d82523d6000602084013e62000617565b606091505b5091509150816200066b5760405162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015260640162000134565b805115620006ea5780806020019051810190620006899190620008ca565b620006ea5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000134565b50505050565b82805482825590600052602060002090810192821562000748579160200282015b828111156200074857825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019062000711565b50620007569291506200075a565b5090565b5b808211156200075657600081556001016200075b565b80516001600160a01b03811681146200078957600080fd5b919050565b600082601f8301126200079f578081fd5b815160206001600160401b0380831115620007be57620007be62000997565b8260051b604051601f19603f83011681018181108482111715620007e657620007e662000997565b6040528481528381019250868401828801850189101562000805578687fd5b8692505b8583101562000832576200081d8162000771565b84529284019260019290920191840162000809565b50979650505050505050565b6000806000806080858703121562000854578384fd5b84516001600160401b03808211156200086b578586fd5b62000879888389016200078e565b955060208701519150808211156200088f578485fd5b506200089e878288016200078e565b935050620008af6040860162000771565b9150620008bf6060860162000771565b905092959194509250565b600060208284031215620008dc578081fd5b81518015158114620008ec578182fd5b9392505050565b60006020828403121562000905578081fd5b5051919050565b60008251815b818110156200092e576020818601810151858301520162000912565b818111156200093d5782828501525b509190910192915050565b6020808252825182820181905260009190848201906040850190845b818110156200098b5783516001600160a01b03168352928401929184019160010162000964565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b60805160601c61480162000a0b6000396000818161073801528181610a420152818161123301528181611edf015281816123ac0152818161288301528181612e2e01528181613089015281816132ca015261351101526148016000f3fe6080604052600436106102c95760003560e01c806391d1485411610179578063b636c2f7116100d6578063d8baf7cf1161008a578063f2fde38b11610064578063f2fde38b14610850578063f874225414610870578063f9a52b71146108a457600080fd5b8063d8baf7cf146107f0578063dd8544b314610810578063dede7f151461083057600080fd5b8063c8a3a5c6116100bb578063c8a3a5c61461079a578063d547741f146107ba578063d73792a9146107da57600080fd5b8063b636c2f71461075a578063c3accd481461077a57600080fd5b8063a3f4df7e1161012d578063ac85dca711610112578063ac85dca7146106e6578063aede369314610706578063b381cf401461072657600080fd5b8063a3f4df7e14610670578063a9059cbb146106c657600080fd5b8063952e90121161015e578063952e901214610626578063a0cf0aea14610646578063a217fddf1461065b57600080fd5b806391d148541461058257806392f5d88a146105c657600080fd5b806352a52ab011610227578063809356aa116101db5780638980f11f116101c05780638980f11f1461052f5780638bb9c5bf1461054f5780638e22b20b1461056f57600080fd5b8063809356aa146104ef578063866a6a041461050f57600080fd5b806376c7a3c71161020c57806376c7a3c7146104af57806376ebe69c146104c55780637c7a561b146104da57600080fd5b806352a52ab01461046f5780636b453c1f1461048f57600080fd5b80632f2ff15d1161027e57806336568abe1161026357806336568abe1461040f5780633a9a40811461042f5780634c09cf4e1461044f57600080fd5b80632f2ff15d146103cf57806331ac9920146103ef57600080fd5b8063061b15e7116102af578063061b15e7146103425780630e86f6661461036f578063248a9ca31461039157600080fd5b8062b99e36146102d557806301ffc9a71461031257600080fd5b366102d057005b600080fd5b3480156102e157600080fd5b506002546102f5906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561031e57600080fd5b5061033261032d366004614100565b6108c4565b6040519015158152602001610309565b34801561034e57600080fd5b5061036261035d36600461437e565b61092d565b60405161030991906145bc565b34801561037b57600080fd5b5061038f61038a366004614128565b610a38565b005b34801561039d57600080fd5b506103c16103ac3660046140b9565b60009081526020819052604090206001015490565b604051908152602001610309565b3480156103db57600080fd5b5061038f6103ea3660046140d1565b610b9c565b3480156103fb57600080fd5b5061038f61040a3660046140b9565b610bc6565b34801561041b57600080fd5b5061038f61042a3660046140d1565b610c97565b34801561043b57600080fd5b5061038f61044a366004613fd2565b610d23565b34801561045b57600080fd5b5061036261046a366004614337565b610dfc565b34801561047b57600080fd5b506102f561048a3660046140b9565b610ee5565b34801561049b57600080fd5b5061038f6104aa366004613f1d565b610f0f565b3480156104bb57600080fd5b506103c160015481565b3480156104d157600080fd5b506003546103c1565b3480156104e657600080fd5b506004546103c1565b3480156104fb57600080fd5b506103c161050a3660046143cf565b610f3c565b34801561051b57600080fd5b5061038f61052a3660046141a3565b611005565b34801561053b57600080fd5b5061038f61054a366004613fc0565b6110e3565b34801561055b57600080fd5b5061038f61056a3660046140b9565b61121e565b61038f61057d366004614128565b611229565b34801561058e57600080fd5b5061033261059d3660046140d1565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b3480156105d257600080fd5b506105e66105e136600461429a565b61135e565b6040805182516001600160a01b03908116825260208085015182169083015283830151169181019190915260609182015191810191909152608001610309565b34801561063257600080fd5b506102f56106413660046140b9565b611521565b34801561065257600080fd5b506102f5600081565b34801561066757600080fd5b506103c1600081565b34801561067c57600080fd5b506106b96040518060400160405280600c81526020017f417661626f74526f75746572000000000000000000000000000000000000000081525081565b6040516103099190614587565b3480156106d257600080fd5b5061038f6106e1366004613f55565b611531565b3480156106f257600080fd5b5061038f610701366004613f80565b6115be565b34801561071257600080fd5b5061038f6107213660046140b9565b611601565b34801561073257600080fd5b506102f57f000000000000000000000000000000000000000000000000000000000000000081565b34801561076657600080fd5b5061038f610775366004614128565b611748565b34801561078657600080fd5b5061038f610795366004613f1d565b61178c565b3480156107a657600080fd5b5061038f6107b5366004613fd2565b611892565b3480156107c657600080fd5b5061038f6107d53660046140d1565b61196b565b3480156107e657600080fd5b506103c161271081565b3480156107fc57600080fd5b5061038f61080b366004613f1d565b611990565b34801561081c57600080fd5b5061038f61082b366004613f1d565b6119ba565b34801561083c57600080fd5b506105e661084b366004614259565b611a5f565b34801561085c57600080fd5b5061038f61086b366004613f1d565b611beb565b34801561087c57600080fd5b506103c17f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab9581565b3480156108b057600080fd5b5061038f6108bf3660046141a3565b611c02565b60006001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061092757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b6109586040518060800160405280606081526020016060815260200160608152602001600081525090565b6000831180156109685750600583105b6109b95760405162461bcd60e51b815260206004820152601f60248201527f417661626f74526f757465723a20496e76616c6964206d61782d73746570730060448201526064015b60405180910390fd5b60006109c58787611e7b565b905060008084116109d75760006109e1565b6109e18487611ece565b90506109f1888888888686611f71565b915081602001515160001415610a23576040805160208082018352600080835291855282519081018352908152908301525b610a2c82612304565b98975050505050505050565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016610a6f6040870187614656565b6001610a7e60408a018a614656565b610a899291506146f5565b818110610aa657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610abb9190613f1d565b6001600160a01b031614610b375760405162461bcd60e51b815260206004820152602960248201527f417661626f74526f757465723a2050617468206e6565647320746f20656e642060448201527f776974682057455448000000000000000000000000000000000000000000000060648201526084016109b0565b6000610b7d863330888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237f92505050565b9050610b888161329b565b610b9460008233613331565b505050505050565b600082815260208190526040902060010154610bb78161339f565b610bc183836133a9565b505050565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff16610c555760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b60015460408051918252602082018490527f4bb8a6184424e4bb853a4836042f5a726e4e710873989bfc6abdab19966f5b70910160405180910390a150600155565b6001600160a01b0381163314610d155760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084016109b0565b610d1f8282613447565b5050565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff16610db25760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b7febf7325f48e05e5e38809c69f8b02a7c907ed31d8768e6c2d841b1296a9225fe82604051610de19190614574565b60405180910390a18151610bc1906004906020850190613e1d565b610e276040518060800160405280606081526020016060815260200160608152602001600081525090565b600082118015610e375750600582105b610e835760405162461bcd60e51b815260206004820152601f60248201527f417661626f74526f757465723a20496e76616c6964206d61782d73746570730060448201526064016109b0565b6000610e8f8686611e7b565b9050610ea086868686856000611f71565b905080602001515160001415610ed2576040805160208082018352600080835291845282519081018352908152908201525b610edb81612304565b9695505050505050565b60038181548110610ef557600080fd5b6000918252602090912001546001600160a01b0316905081565b610f397f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab9582610b9c565b50565b60008060048360ff1681548110610f6357634e487b7160e01b600052603260045260246000fd5b60009182526020822001546040516377ccc49d60e11b8152600481018990526001600160a01b03888116602483015287811660448301529091169250829063ef99893a9060640160206040518083038186803b158015610fc257600080fd5b505afa158015610fd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ffa9190614241565b979650505050505050565b6110126040890189614656565b600081811061103157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906110469190613f1d565b60405163d505accf60e01b8152336004820152306024820152893560448201526064810188905260ff8516608482015260a4810184905260c481018390526001600160a01b03919091169063d505accf9060e401600060405180830381600087803b1580156110b457600080fd5b505af11580156110c8573d6000803e3d6000fd5b505050506110d98888888888610a38565b5050505050505050565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff166111725760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b600082116111c25760405162461bcd60e51b815260206004820152601260248201527f4e6f7468696e6720746f207265636f766572000000000000000000000000000060448201526064016109b0565b6111d66001600160a01b03841633846134c6565b826001600160a01b03167f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa288360405161121191815260200190565b60405180910390a2505050565b33610d1f8282610c97565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166112606040870187614656565b600081811061127f57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906112949190613f1d565b6001600160a01b0316146113105760405162461bcd60e51b815260206004820152602b60248201527f417661626f74526f757465723a2050617468206e6565647320746f206265676960448201527f6e2077697468205745544800000000000000000000000000000000000000000060648201526084016109b0565b61131a853561350f565b610b94853033878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237f92505050565b60408051608081018252600080825260208201819052918101829052606081019190915260408051608081018252600080825260208201819052918101829052606081019190915260005b60ff8116841115611516576000600486868460ff168181106113db57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906113f0919061441f565b60ff168154811061141157634e487b7160e01b600052603260045260246000fd5b60009182526020822001546040516377ccc49d60e11b8152600481018c90526001600160a01b038b811660248301528a811660448301529091169250829063ef99893a9060640160206040518083038186803b15801561147057600080fd5b505afa158015611484573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a89190614241565b905060ff831615806114bd5750836060015181115b15611501576040518060800160405280836001600160a01b031681526020018a6001600160a01b03168152602001896001600160a01b031681526020018281525093505b5050808061150e9061476a565b9150506113a9565b509695505050505050565b60048181548110610ef557600080fd5b61153961357e565b6001600160a01b038216611560576040516309293b1960e41b815260040160405180910390fd5b600080600080600085875af1905080610bc1576040517fc8776798000000000000000000000000000000000000000000000000000000008152600060048201526001600160a01b0384166024820152604481018390526064016109b0565b6115c661357e565b6001600160a01b0382166115ed576040516309293b1960e41b815260040160405180910390fd5b610bc16001600160a01b03841683836134c6565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff166116905760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b600082116116e05760405162461bcd60e51b815260206004820152601260248201527f4e6f7468696e6720746f207265636f766572000000000000000000000000000060448201526064016109b0565b604051339083156108fc029084906000818181858888f1935050505015801561170d573d6000803e3d6000fd5b506040518281526000907f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa289060200160405180910390a25050565b610b94853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237f92505050565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff1661181b5760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b600254604080516001600160a01b03928316815291841660208301527fb2c853ac4d80d18d058c43d8018d077a036e542a79acae1647f5ad2a8c76f4e2910160405180910390a1506002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff166119215760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b7f658ff1688002926d8f426cb10c052ec29003f50042df9652d8613484c1a58647826040516119509190614574565b60405180910390a18151610bc1906003906020850190613e1d565b6000828152602081905260409020600101546119868161339f565b610bc18383613447565b610f397f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab958261196b565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff16611a495760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b610d1f6001600160a01b03831683600019611cd6565b60408051608081018252600080825260208201819052918101829052606081019190915260408051608081018252600080825260208201819052918101829052606081019190915260005b60045460ff82161015611be257600060048260ff1681548110611add57634e487b7160e01b600052603260045260246000fd5b60009182526020822001546040516377ccc49d60e11b8152600481018a90526001600160a01b03898116602483015288811660448301529091169250829063ef99893a9060640160206040518083038186803b158015611b3c57600080fd5b505afa158015611b50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b749190614241565b905060ff83161580611b895750836060015181115b15611bcd576040518060800160405280836001600160a01b03168152602001886001600160a01b03168152602001876001600160a01b031681526020018281525093505b50508080611bda9061476a565b915050611aaa565b50949350505050565b33611bf7600083610b9c565b610d1f600082610c97565b611c0f6040890189614656565b6000818110611c2e57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611c439190613f1d565b60405163d505accf60e01b8152336004820152306024820152893560448201526064810188905260ff8516608482015260a4810184905260c481018390526001600160a01b03919091169063d505accf9060e401600060405180830381600087803b158015611cb157600080fd5b505af1158015611cc5573d6000803e3d6000fd5b505050506110d98888888888611748565b801580611d7857506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015611d3e57600080fd5b505afa158015611d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d769190614241565b155b611dea5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016109b0565b6040516001600160a01b038316602482015260448101829052610bc19084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909316929092179091526135cf565b611ea66040518060800160405280606081526020016060815260200160608152602001600081525090565b611eaf8361370b565b8152611ec36001600160a01b03831661370b565b604082015292915050565b600080611f06670de0b6b3a76400007f0000000000000000000000000000000000000000000000000000000000000000856002610dfc565b9050806040015151600014611f6a5780518051633b9aca00918691611f2d906001906146f5565b81518110611f4b57634e487b7160e01b600052603260045260246000fd5b6020026020010151611f5d91906146d6565b611f6791906146b6565b91505b5092915050565b611f9c6040518060800160405280606081526020016060815260200160608152602001600081525090565b6000611fa784613735565b905060008084151581611fbb8c8c8c611a5f565b905080606001516000146120695781156120475780600001516001600160a01b03166369cff80d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561200c57600080fd5b505afa158015612020573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120449190614241565b92505b606081015181516040830151612061928892909187613798565b806060015193505b600189118015612094575061207f60028a6146f5565b602089602001515161209191906146b6565b11155b156122f45760005b6003548110156122f257600381815481106120c757634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b038d8116911614156120eb576122e0565b600061212d8e8e6003858154811061211357634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0316611a5f565b905080606001516000141561214257506122e0565b600061214d8b613735565b905084156121cd5781600001516001600160a01b03166369cff80d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561219257600080fd5b505afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190614241565b95505b6060820151825160408401516121e792849290918a613798565b61222e82606001516003858154811061221057634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b03168f8f858f611f71565b9050600061223b8261385c565b905060006122488361386f565b9050816001600160a01b03168f6001600160a01b031614801561226a57508881115b156122db578960600151836060015111156122d4576000633b9aca008b60600151856060015161229a91906146f5565b6122a4908f6146d6565b6122ae91906146b6565b905060006122bc8b846146f5565b9050808211156122d1575050505050506122e0565b50505b8098508299505b505050505b806122ea8161474f565b91505061209c565b505b50929a9950505050505050505050565b61232f6040518060800160405280606081526020016060815260200160608152602001600081525090565b60405180608001604052806123478460000151613884565b81526020016123598460200151613960565b815260200161236b8460400151613960565b815260200183606001518152509050919050565b60008261238b81613a33565b60008086118061239d57506000600154115b156124db576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166123d960408b018b614656565b60016123e860408e018e614656565b6123f39291506146f5565b81811061241057634e487b7160e01b600052603260045260246000fd5b90506020020160208101906124259190613f1d565b6001600160a01b0316146124d35761243e893587613a6d565b90503361244e60408b018b614656565b600081811061246d57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906124829190613f1d565b6001600160a01b03167fe6cdb6e1f794aa8f4cd0ecfaa3049c808c84128ff20f1d9fb6958809d32e51ef866124b8858e356146f5565b6040516124c692919061459a565b60405180910390a36124df565b5087356124df565b5087355b6124ec60608a018a614656565b600081811061250b57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906125209190613f1d565b6001600160a01b031663a5bfdcaf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561255857600080fd5b505afa15801561256c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125909190614099565b156127b05760006125a460608b018b614656565b60008181106125c357634e487b7160e01b600052603260045260246000fd5b90506020020160208101906125d89190613f1d565b6001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b15801561261057600080fd5b505afa158015612624573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126489190613f39565b90506127aa61265a60408c018c614656565b600081811061267957634e487b7160e01b600052603260045260246000fd5b905060200201602081019061268e9190613f1d565b8a836001600160a01b031663e6a439058e80604001906126ae9190614656565b60008181106126cd57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906126e29190613f1d565b8f80604001906126f29190614656565b600181811061271157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906127269190613f1d565b6040516001600160e01b031960e085901b1681526001600160a01b0392831660048201529116602482015260440160206040518083038186803b15801561276c57600080fd5b505afa158015612780573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127a49190613f39565b85613ae9565b5061283c565b61283c6127c060408b018b614656565b60008181106127df57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906127f49190613f1d565b8961280260608d018d614656565b600081811061282157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906128369190613f1d565b84613ae9565b5060408051600280825260608201835260009260208301908036833701905050905060005b61286e60608b018b614656565b9050811015612e0c5760006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166128b060408d018d614656565b60018e80604001906128c29190614656565b6128cd9291506146f5565b8181106128ea57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906128ff9190613f1d565b6001600160a01b0316141561298557600161291d60608d018d614656565b6129289291506146f5565b8210612934573061297e565b61294160608c018c614656565b61294c84600161469e565b81811061296957634e487b7160e01b600052603260045260246000fd5b905060200201602081019061297e9190613f1d565b90506129f8565b600161299460608d018d614656565b61299f9291506146f5565b82106129ab57886129f5565b6129b860608c018c614656565b6129c384600161469e565b8181106129e057634e487b7160e01b600052603260045260246000fd5b90506020020160208101906129f59190613f1d565b90505b612a0560408c018c614656565b612a1084600161469e565b818110612a2d57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612a429190613f1d565b6040516370a0823160e01b81526001600160a01b03838116600483015291909116906370a082319060240160206040518083038186803b158015612a8557600080fd5b505afa158015612a99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abd9190614241565b83600081518110612ade57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152612af660608c018c614656565b83818110612b1457634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612b299190613f1d565b6001600160a01b031663eab90da66000808e8060400190612b4a9190614656565b87818110612b6857634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612b7d9190613f1d565b8f8060400190612b8d9190614656565b612b9889600161469e565b818110612bb557634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612bca9190613f1d565b6040516001600160e01b031960e087901b168152600481019490945260248401929092526001600160a01b03908116604484015290811660648301528416608482015260a401600060405180830381600087803b158015612c2a57600080fd5b505af1158015612c3e573d6000803e3d6000fd5b5060019250612c5391505060608d018d614656565b612c5e9291506146f5565b821415612df957600083600081518110612c8857634e487b7160e01b600052603260045260246000fd5b60200260200101518c8060400190612ca09190614656565b612cab86600161469e565b818110612cc857634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612cdd9190613f1d565b6040516370a0823160e01b81526001600160a01b03858116600483015291909116906370a082319060240160206040518083038186803b158015612d2057600080fd5b505afa158015612d34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d589190614241565b612d6291906146f5565b90508b60200135811015612dc95760405162461bcd60e51b815260206004820152602860248201527f417661626f74526f757465723a20496e73756666696369656e74206f757470756044820152671d08185b5bdd5b9d60c21b60648201526084016109b0565b8084600181518110612deb57634e487b7160e01b600052603260045260246000fd5b602002602001018181525050505b5080612e048161474f565b915050612861565b50600080871180612e1f57506000600154115b15613053576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612e5b60408c018c614656565b6001612e6a60408f018f614656565b612e759291506146f5565b818110612e9257634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612ea79190613f1d565b6001600160a01b0316141561302357612ee882600181518110612eda57634e487b7160e01b600052603260045260246000fd5b602002602001015188613a6d565b90508960200135811015612f4f5760405162461bcd60e51b815260206004820152602860248201527f417661626f74526f757465723a20496e73756666696369656e74206f757470756044820152671d08185b5bdd5b9d60c21b60648201526084016109b0565b33612f5d60408c018c614656565b6001612f6c60408f018f614656565b612f779291506146f5565b818110612f9457634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612fa99190613f1d565b6001600160a01b03167fe6cdb6e1f794aa8f4cd0ecfaa3049c808c84128ff20f1d9fb6958809d32e51ef878486600181518110612ff657634e487b7160e01b600052603260045260246000fd5b602002602001015161300891906146f5565b60405161301692919061459a565b60405180910390a361307f565b8160018151811061304457634e487b7160e01b600052603260045260246000fd5b6020026020010151905061307f565b8160018151811061307457634e487b7160e01b600052603260045260246000fd5b602002602001015190505b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166130b660408c018c614656565b60016130c560408f018f614656565b6130d09291506146f5565b8181106130ed57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906131029190613f1d565b6001600160a01b031614801561312157506001600160a01b0388163014155b1561319757613197888261313860408e018e614656565b60018f806040019061314a9190614656565b6131559291506146f5565b81811061317257634e487b7160e01b600052603260045260246000fd5b90506020020160208101906131879190613f1d565b6001600160a01b031691906134c6565b6131a460408b018b614656565b60016131b360408e018e614656565b6131be9291506146f5565b8181106131db57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906131f09190613f1d565b6001600160a01b031661320660408c018c614656565b600081811061322557634e487b7160e01b600052603260045260246000fd5b905060200201602081019061323a9190613f1d565b604080518d358152602081018590523381830152606081018b905290516001600160a01b0392909216917f361ceb771316054c3316cb5ecd6c9fa73d64cf7ff4248052cb4df39178a6ec729181900360800190a39998505050505050505050565b6040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561331657600080fd5b505af115801561332a573d6000803e3d6000fd5b5050505050565b306001600160a01b03821614610bc1576001600160a01b03831661338b576040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015613385573d6000803e3d6000fd5b50505050565b610bc16001600160a01b03841682846134c6565b610f398133613b27565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610d1f576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556134033390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610d1f576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6040516001600160a01b038316602482015260448101829052610bc19084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611e2f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561356a57600080fd5b505af1158015610b94573d6000803e3d6000fd5b60025433906001600160a01b03168114610f39576040517fd7af094e0000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016109b0565b600080836001600160a01b0316836040516135ea91906144a8565b6000604051808303816000865af19150503d8060008114613627576040519150601f19603f3d011682016040523d82523d6000602084013e61362c565b606091505b50915091508161367e5760405162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656460448201526064016109b0565b80511561338557808060200190518101906136999190614099565b6133855760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016109b0565b60408051602080825281830190925260609160208201818036833750505060208101929092525090565b6137606040518060800160405280606081526020016060815260200160608152602001600081525090565b604051806080016040528083600001518152602001836020015181526020018360400151815260200183606001518152509050919050565b84604001516137af836001600160a01b031661370b565b6040516020016137c09291906144c4565b60408051601f1981840301815291815286015260208501516137ea6001600160a01b03851661370b565b6040516020016137fb9291906144c4565b60408051601f198184030181529190526020860152845161381b8561370b565b60405160200161382c9291906144c4565b60408051601f19818403018152919052855260608501805182919061385290839061469e565b9052505050505050565b6040810151805160009161092791613918565b60408101515181516000916109279190613918565b60606020825161389491906146b6565b67ffffffffffffffff8111156138ba57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156138e3578160200160208202803683370190505b50905060005b602083516138f791906146b6565b81101561395a5761391d8361390d8360206146d6565b61391890602061469e565b015190565b82828151811061393d57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152806139528161474f565b9150506138e9565b50919050565b60606020825161397091906146b6565b67ffffffffffffffff81111561399657634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156139bf578160200160208202803683370190505b50905060005b602083516139d391906146b6565b81101561395a576139e98361390d8360206146d6565b828281518110613a0957634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280613a2b8161474f565b9150506139c5565b42811015610f39576040517fa83116fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600154821015613ac15760405162461bcd60e51b815260206004820152601e60248201527f417661626f74526f757465723a20496e73756666696369656e7420666565000060448201526064016109b0565b612710613ace83826146f5565b613ad890856146d6565b613ae291906146b6565b9392505050565b6001600160a01b0383163014613b1357613b0e6001600160a01b038516848484613ba5565b613385565b6133856001600160a01b03851683836134c6565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610d1f57613b63816001600160a01b03166014613bf6565b613b6e836020613bf6565b604051602001613b7f9291906144f3565b60408051601f198184030181529082905262461bcd60e51b82526109b091600401614587565b6040516001600160a01b03808516602483015283166044820152606481018290526133859085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611e2f565b60606000613c058360026146d6565b613c1090600261469e565b67ffffffffffffffff811115613c3657634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613c60576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110613ca557634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110613cfe57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000613d228460026146d6565b613d2d90600161469e565b90505b6001811115613dce577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613d7c57634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110613da057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93613dc781614738565b9050613d30565b508315613ae25760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109b0565b828054828255906000526020600020908101928215613e7f579160200282015b82811115613e7f578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e3d565b50613e8b929150613e8f565b5090565b5b80821115613e8b5760008155600101613e90565b8035613eaf816147b6565b919050565b60008083601f840112613ec5578182fd5b50813567ffffffffffffffff811115613edc578182fd5b602083019150836020828501011115613ef457600080fd5b9250929050565b60006080828403121561395a578081fd5b803560ff81168114613eaf57600080fd5b600060208284031215613f2e578081fd5b8135613ae2816147b6565b600060208284031215613f4a578081fd5b8151613ae2816147b6565b60008060408385031215613f67578081fd5b8235613f72816147b6565b946020939093013593505050565b600080600060608486031215613f94578081fd5b8335613f9f816147b6565b92506020840135613faf816147b6565b929592945050506040919091013590565b60008060408385031215613f67578182fd5b60006020808385031215613fe4578182fd5b823567ffffffffffffffff80821115613ffb578384fd5b818501915085601f83011261400e578384fd5b813581811115614020576140206147a0565b8060051b604051601f19603f83011681018181108582111715614045576140456147a0565b604052828152858101935084860182860187018a1015614063578788fd5b8795505b8386101561408c5761407881613ea4565b855260019590950194938601938601614067565b5098975050505050505050565b6000602082840312156140aa578081fd5b81518015158114613ae2578182fd5b6000602082840312156140ca578081fd5b5035919050565b600080604083850312156140e3578182fd5b8235915060208301356140f5816147b6565b809150509250929050565b600060208284031215614111578081fd5b81356001600160e01b031981168114613ae2578182fd5b60008060008060006080868803121561413f578081fd5b853567ffffffffffffffff80821115614156578283fd5b61416289838a01613efb565b965060208801359550604088013594506060880135915080821115614185578283fd5b5061419288828901613eb4565b969995985093965092949392505050565b60008060008060008060008060e0898b0312156141be578283fd5b883567ffffffffffffffff808211156141d5578485fd5b6141e18c838d01613efb565b995060208b0135985060408b0135975060608b0135915080821115614204578485fd5b506142118b828c01613eb4565b9096509450614224905060808a01613f0c565b925060a0890135915060c089013590509295985092959890939650565b600060208284031215614252578081fd5b5051919050565b60008060006060848603121561426d578081fd5b83359250602084013561427f816147b6565b9150604084013561428f816147b6565b809150509250925092565b6000806000806000608086880312156142b1578283fd5b8535945060208601356142c3816147b6565b935060408601356142d3816147b6565b9250606086013567ffffffffffffffff808211156142ef578283fd5b818801915088601f830112614302578283fd5b813581811115614310578384fd5b8960208260051b8501011115614324578384fd5b9699959850939650602001949392505050565b6000806000806080858703121561434c578182fd5b84359350602085013561435e816147b6565b9250604085013561436e816147b6565b9396929550929360600135925050565b600080600080600060a08688031215614395578283fd5b8535945060208601356143a7816147b6565b935060408601356143b7816147b6565b94979396509394606081013594506080013592915050565b600080600080608085870312156143e4578182fd5b8435935060208501356143f6816147b6565b92506040850135614406816147b6565b915061441460608601613f0c565b905092959194509250565b600060208284031215614430578081fd5b613ae282613f0c565b6000815180845260208085019450808401835b838110156144715781516001600160a01b03168752958201959082019060010161444c565b509495945050505050565b6000815180845261449481602086016020860161470c565b601f01601f19169290920160200192915050565b600082516144ba81846020870161470c565b9190910192915050565b600083516144d681846020880161470c565b8351908301906144ea81836020880161470c565b01949350505050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161452b81601785016020880161470c565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000601791840191820152835161456881602884016020880161470c565b01602801949350505050565b602081526000613ae26020830184614439565b602081526000613ae2602083018461447c565b6040815260006145ad604083018561447c565b90508260208301529392505050565b60208082528251608083830152805160a0840181905260009291820190839060c08601905b8083101561460157835182529284019260019290920191908401906145e1565b50838701519350601f199250828682030160408701526146218185614439565b9350505060408501518185840301606086015261463e8382614439565b92505050606084015160808401528091505092915050565b6000808335601e1984360301811261466c578283fd5b83018035915067ffffffffffffffff821115614686578283fd5b6020019150600581901b3603821315613ef457600080fd5b600082198211156146b1576146b161478a565b500190565b6000826146d157634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156146f0576146f061478a565b500290565b6000828210156147075761470761478a565b500390565b60005b8381101561472757818101518382015260200161470f565b838111156133855750506000910152565b6000816147475761474761478a565b506000190190565b60006000198214156147635761476361478a565b5060010190565b600060ff821660ff8114156147815761478161478a565b60010192915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610f3957600080fdfea2646970667358221220ad6740f747a1a00a36f8954b4a203d529f7f34ef9ff2772d1851629c54e4c71f64736f6c63430008040033a54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d394d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d61000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000063817b3683c2477398129c54d44682cd7a86b9db000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000200000000000000000000000008d06e6d98d757f5128c12e8c9a0ecdad825b0b20000000000000000000000006734503b71c4b004513512709fc547f6de2c08600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Deployed Bytecode
0x6080604052600436106102c95760003560e01c806391d1485411610179578063b636c2f7116100d6578063d8baf7cf1161008a578063f2fde38b11610064578063f2fde38b14610850578063f874225414610870578063f9a52b71146108a457600080fd5b8063d8baf7cf146107f0578063dd8544b314610810578063dede7f151461083057600080fd5b8063c8a3a5c6116100bb578063c8a3a5c61461079a578063d547741f146107ba578063d73792a9146107da57600080fd5b8063b636c2f71461075a578063c3accd481461077a57600080fd5b8063a3f4df7e1161012d578063ac85dca711610112578063ac85dca7146106e6578063aede369314610706578063b381cf401461072657600080fd5b8063a3f4df7e14610670578063a9059cbb146106c657600080fd5b8063952e90121161015e578063952e901214610626578063a0cf0aea14610646578063a217fddf1461065b57600080fd5b806391d148541461058257806392f5d88a146105c657600080fd5b806352a52ab011610227578063809356aa116101db5780638980f11f116101c05780638980f11f1461052f5780638bb9c5bf1461054f5780638e22b20b1461056f57600080fd5b8063809356aa146104ef578063866a6a041461050f57600080fd5b806376c7a3c71161020c57806376c7a3c7146104af57806376ebe69c146104c55780637c7a561b146104da57600080fd5b806352a52ab01461046f5780636b453c1f1461048f57600080fd5b80632f2ff15d1161027e57806336568abe1161026357806336568abe1461040f5780633a9a40811461042f5780634c09cf4e1461044f57600080fd5b80632f2ff15d146103cf57806331ac9920146103ef57600080fd5b8063061b15e7116102af578063061b15e7146103425780630e86f6661461036f578063248a9ca31461039157600080fd5b8062b99e36146102d557806301ffc9a71461031257600080fd5b366102d057005b600080fd5b3480156102e157600080fd5b506002546102f5906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561031e57600080fd5b5061033261032d366004614100565b6108c4565b6040519015158152602001610309565b34801561034e57600080fd5b5061036261035d36600461437e565b61092d565b60405161030991906145bc565b34801561037b57600080fd5b5061038f61038a366004614128565b610a38565b005b34801561039d57600080fd5b506103c16103ac3660046140b9565b60009081526020819052604090206001015490565b604051908152602001610309565b3480156103db57600080fd5b5061038f6103ea3660046140d1565b610b9c565b3480156103fb57600080fd5b5061038f61040a3660046140b9565b610bc6565b34801561041b57600080fd5b5061038f61042a3660046140d1565b610c97565b34801561043b57600080fd5b5061038f61044a366004613fd2565b610d23565b34801561045b57600080fd5b5061036261046a366004614337565b610dfc565b34801561047b57600080fd5b506102f561048a3660046140b9565b610ee5565b34801561049b57600080fd5b5061038f6104aa366004613f1d565b610f0f565b3480156104bb57600080fd5b506103c160015481565b3480156104d157600080fd5b506003546103c1565b3480156104e657600080fd5b506004546103c1565b3480156104fb57600080fd5b506103c161050a3660046143cf565b610f3c565b34801561051b57600080fd5b5061038f61052a3660046141a3565b611005565b34801561053b57600080fd5b5061038f61054a366004613fc0565b6110e3565b34801561055b57600080fd5b5061038f61056a3660046140b9565b61121e565b61038f61057d366004614128565b611229565b34801561058e57600080fd5b5061033261059d3660046140d1565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b3480156105d257600080fd5b506105e66105e136600461429a565b61135e565b6040805182516001600160a01b03908116825260208085015182169083015283830151169181019190915260609182015191810191909152608001610309565b34801561063257600080fd5b506102f56106413660046140b9565b611521565b34801561065257600080fd5b506102f5600081565b34801561066757600080fd5b506103c1600081565b34801561067c57600080fd5b506106b96040518060400160405280600c81526020017f417661626f74526f75746572000000000000000000000000000000000000000081525081565b6040516103099190614587565b3480156106d257600080fd5b5061038f6106e1366004613f55565b611531565b3480156106f257600080fd5b5061038f610701366004613f80565b6115be565b34801561071257600080fd5b5061038f6107213660046140b9565b611601565b34801561073257600080fd5b506102f57f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b34801561076657600080fd5b5061038f610775366004614128565b611748565b34801561078657600080fd5b5061038f610795366004613f1d565b61178c565b3480156107a657600080fd5b5061038f6107b5366004613fd2565b611892565b3480156107c657600080fd5b5061038f6107d53660046140d1565b61196b565b3480156107e657600080fd5b506103c161271081565b3480156107fc57600080fd5b5061038f61080b366004613f1d565b611990565b34801561081c57600080fd5b5061038f61082b366004613f1d565b6119ba565b34801561083c57600080fd5b506105e661084b366004614259565b611a5f565b34801561085c57600080fd5b5061038f61086b366004613f1d565b611beb565b34801561087c57600080fd5b506103c17f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab9581565b3480156108b057600080fd5b5061038f6108bf3660046141a3565b611c02565b60006001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061092757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b6109586040518060800160405280606081526020016060815260200160608152602001600081525090565b6000831180156109685750600583105b6109b95760405162461bcd60e51b815260206004820152601f60248201527f417661626f74526f757465723a20496e76616c6964206d61782d73746570730060448201526064015b60405180910390fd5b60006109c58787611e7b565b905060008084116109d75760006109e1565b6109e18487611ece565b90506109f1888888888686611f71565b915081602001515160001415610a23576040805160208082018352600080835291855282519081018352908152908301525b610a2c82612304565b98975050505050505050565b6001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216610a6f6040870187614656565b6001610a7e60408a018a614656565b610a899291506146f5565b818110610aa657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610abb9190613f1d565b6001600160a01b031614610b375760405162461bcd60e51b815260206004820152602960248201527f417661626f74526f757465723a2050617468206e6565647320746f20656e642060448201527f776974682057455448000000000000000000000000000000000000000000000060648201526084016109b0565b6000610b7d863330888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237f92505050565b9050610b888161329b565b610b9460008233613331565b505050505050565b600082815260208190526040902060010154610bb78161339f565b610bc183836133a9565b505050565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff16610c555760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b60015460408051918252602082018490527f4bb8a6184424e4bb853a4836042f5a726e4e710873989bfc6abdab19966f5b70910160405180910390a150600155565b6001600160a01b0381163314610d155760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084016109b0565b610d1f8282613447565b5050565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff16610db25760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b7febf7325f48e05e5e38809c69f8b02a7c907ed31d8768e6c2d841b1296a9225fe82604051610de19190614574565b60405180910390a18151610bc1906004906020850190613e1d565b610e276040518060800160405280606081526020016060815260200160608152602001600081525090565b600082118015610e375750600582105b610e835760405162461bcd60e51b815260206004820152601f60248201527f417661626f74526f757465723a20496e76616c6964206d61782d73746570730060448201526064016109b0565b6000610e8f8686611e7b565b9050610ea086868686856000611f71565b905080602001515160001415610ed2576040805160208082018352600080835291845282519081018352908152908201525b610edb81612304565b9695505050505050565b60038181548110610ef557600080fd5b6000918252602090912001546001600160a01b0316905081565b610f397f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab9582610b9c565b50565b60008060048360ff1681548110610f6357634e487b7160e01b600052603260045260246000fd5b60009182526020822001546040516377ccc49d60e11b8152600481018990526001600160a01b03888116602483015287811660448301529091169250829063ef99893a9060640160206040518083038186803b158015610fc257600080fd5b505afa158015610fd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ffa9190614241565b979650505050505050565b6110126040890189614656565b600081811061103157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906110469190613f1d565b60405163d505accf60e01b8152336004820152306024820152893560448201526064810188905260ff8516608482015260a4810184905260c481018390526001600160a01b03919091169063d505accf9060e401600060405180830381600087803b1580156110b457600080fd5b505af11580156110c8573d6000803e3d6000fd5b505050506110d98888888888610a38565b5050505050505050565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff166111725760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b600082116111c25760405162461bcd60e51b815260206004820152601260248201527f4e6f7468696e6720746f207265636f766572000000000000000000000000000060448201526064016109b0565b6111d66001600160a01b03841633846134c6565b826001600160a01b03167f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa288360405161121191815260200190565b60405180910390a2505050565b33610d1f8282610c97565b6001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2166112606040870187614656565b600081811061127f57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906112949190613f1d565b6001600160a01b0316146113105760405162461bcd60e51b815260206004820152602b60248201527f417661626f74526f757465723a2050617468206e6565647320746f206265676960448201527f6e2077697468205745544800000000000000000000000000000000000000000060648201526084016109b0565b61131a853561350f565b610b94853033878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237f92505050565b60408051608081018252600080825260208201819052918101829052606081019190915260408051608081018252600080825260208201819052918101829052606081019190915260005b60ff8116841115611516576000600486868460ff168181106113db57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906113f0919061441f565b60ff168154811061141157634e487b7160e01b600052603260045260246000fd5b60009182526020822001546040516377ccc49d60e11b8152600481018c90526001600160a01b038b811660248301528a811660448301529091169250829063ef99893a9060640160206040518083038186803b15801561147057600080fd5b505afa158015611484573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a89190614241565b905060ff831615806114bd5750836060015181115b15611501576040518060800160405280836001600160a01b031681526020018a6001600160a01b03168152602001896001600160a01b031681526020018281525093505b5050808061150e9061476a565b9150506113a9565b509695505050505050565b60048181548110610ef557600080fd5b61153961357e565b6001600160a01b038216611560576040516309293b1960e41b815260040160405180910390fd5b600080600080600085875af1905080610bc1576040517fc8776798000000000000000000000000000000000000000000000000000000008152600060048201526001600160a01b0384166024820152604481018390526064016109b0565b6115c661357e565b6001600160a01b0382166115ed576040516309293b1960e41b815260040160405180910390fd5b610bc16001600160a01b03841683836134c6565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff166116905760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b600082116116e05760405162461bcd60e51b815260206004820152601260248201527f4e6f7468696e6720746f207265636f766572000000000000000000000000000060448201526064016109b0565b604051339083156108fc029084906000818181858888f1935050505015801561170d573d6000803e3d6000fd5b506040518281526000907f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa289060200160405180910390a25050565b610b94853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237f92505050565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff1661181b5760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b600254604080516001600160a01b03928316815291841660208301527fb2c853ac4d80d18d058c43d8018d077a036e542a79acae1647f5ad2a8c76f4e2910160405180910390a1506002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff166119215760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b7f658ff1688002926d8f426cb10c052ec29003f50042df9652d8613484c1a58647826040516119509190614574565b60405180910390a18151610bc1906003906020850190613e1d565b6000828152602081905260409020600101546119868161339f565b610bc18383613447565b610f397f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab958261196b565b3360008181527fa54247010af6b3693b80aceddfad12e077c5de3571e6243fada502635f0d7d39602052604090205460ff16611a495760405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b60648201526084016109b0565b610d1f6001600160a01b03831683600019611cd6565b60408051608081018252600080825260208201819052918101829052606081019190915260408051608081018252600080825260208201819052918101829052606081019190915260005b60045460ff82161015611be257600060048260ff1681548110611add57634e487b7160e01b600052603260045260246000fd5b60009182526020822001546040516377ccc49d60e11b8152600481018a90526001600160a01b03898116602483015288811660448301529091169250829063ef99893a9060640160206040518083038186803b158015611b3c57600080fd5b505afa158015611b50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b749190614241565b905060ff83161580611b895750836060015181115b15611bcd576040518060800160405280836001600160a01b03168152602001886001600160a01b03168152602001876001600160a01b031681526020018281525093505b50508080611bda9061476a565b915050611aaa565b50949350505050565b33611bf7600083610b9c565b610d1f600082610c97565b611c0f6040890189614656565b6000818110611c2e57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611c439190613f1d565b60405163d505accf60e01b8152336004820152306024820152893560448201526064810188905260ff8516608482015260a4810184905260c481018390526001600160a01b03919091169063d505accf9060e401600060405180830381600087803b158015611cb157600080fd5b505af1158015611cc5573d6000803e3d6000fd5b505050506110d98888888888611748565b801580611d7857506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015611d3e57600080fd5b505afa158015611d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d769190614241565b155b611dea5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016109b0565b6040516001600160a01b038316602482015260448101829052610bc19084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909316929092179091526135cf565b611ea66040518060800160405280606081526020016060815260200160608152602001600081525090565b611eaf8361370b565b8152611ec36001600160a01b03831661370b565b604082015292915050565b600080611f06670de0b6b3a76400007f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2856002610dfc565b9050806040015151600014611f6a5780518051633b9aca00918691611f2d906001906146f5565b81518110611f4b57634e487b7160e01b600052603260045260246000fd5b6020026020010151611f5d91906146d6565b611f6791906146b6565b91505b5092915050565b611f9c6040518060800160405280606081526020016060815260200160608152602001600081525090565b6000611fa784613735565b905060008084151581611fbb8c8c8c611a5f565b905080606001516000146120695781156120475780600001516001600160a01b03166369cff80d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561200c57600080fd5b505afa158015612020573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120449190614241565b92505b606081015181516040830151612061928892909187613798565b806060015193505b600189118015612094575061207f60028a6146f5565b602089602001515161209191906146b6565b11155b156122f45760005b6003548110156122f257600381815481106120c757634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b038d8116911614156120eb576122e0565b600061212d8e8e6003858154811061211357634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0316611a5f565b905080606001516000141561214257506122e0565b600061214d8b613735565b905084156121cd5781600001516001600160a01b03166369cff80d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561219257600080fd5b505afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca9190614241565b95505b6060820151825160408401516121e792849290918a613798565b61222e82606001516003858154811061221057634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b03168f8f858f611f71565b9050600061223b8261385c565b905060006122488361386f565b9050816001600160a01b03168f6001600160a01b031614801561226a57508881115b156122db578960600151836060015111156122d4576000633b9aca008b60600151856060015161229a91906146f5565b6122a4908f6146d6565b6122ae91906146b6565b905060006122bc8b846146f5565b9050808211156122d1575050505050506122e0565b50505b8098508299505b505050505b806122ea8161474f565b91505061209c565b505b50929a9950505050505050505050565b61232f6040518060800160405280606081526020016060815260200160608152602001600081525090565b60405180608001604052806123478460000151613884565b81526020016123598460200151613960565b815260200161236b8460400151613960565b815260200183606001518152509050919050565b60008261238b81613a33565b60008086118061239d57506000600154115b156124db576001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2166123d960408b018b614656565b60016123e860408e018e614656565b6123f39291506146f5565b81811061241057634e487b7160e01b600052603260045260246000fd5b90506020020160208101906124259190613f1d565b6001600160a01b0316146124d35761243e893587613a6d565b90503361244e60408b018b614656565b600081811061246d57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906124829190613f1d565b6001600160a01b03167fe6cdb6e1f794aa8f4cd0ecfaa3049c808c84128ff20f1d9fb6958809d32e51ef866124b8858e356146f5565b6040516124c692919061459a565b60405180910390a36124df565b5087356124df565b5087355b6124ec60608a018a614656565b600081811061250b57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906125209190613f1d565b6001600160a01b031663a5bfdcaf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561255857600080fd5b505afa15801561256c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125909190614099565b156127b05760006125a460608b018b614656565b60008181106125c357634e487b7160e01b600052603260045260246000fd5b90506020020160208101906125d89190613f1d565b6001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b15801561261057600080fd5b505afa158015612624573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126489190613f39565b90506127aa61265a60408c018c614656565b600081811061267957634e487b7160e01b600052603260045260246000fd5b905060200201602081019061268e9190613f1d565b8a836001600160a01b031663e6a439058e80604001906126ae9190614656565b60008181106126cd57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906126e29190613f1d565b8f80604001906126f29190614656565b600181811061271157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906127269190613f1d565b6040516001600160e01b031960e085901b1681526001600160a01b0392831660048201529116602482015260440160206040518083038186803b15801561276c57600080fd5b505afa158015612780573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127a49190613f39565b85613ae9565b5061283c565b61283c6127c060408b018b614656565b60008181106127df57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906127f49190613f1d565b8961280260608d018d614656565b600081811061282157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906128369190613f1d565b84613ae9565b5060408051600280825260608201835260009260208301908036833701905050905060005b61286e60608b018b614656565b9050811015612e0c5760006001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2166128b060408d018d614656565b60018e80604001906128c29190614656565b6128cd9291506146f5565b8181106128ea57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906128ff9190613f1d565b6001600160a01b0316141561298557600161291d60608d018d614656565b6129289291506146f5565b8210612934573061297e565b61294160608c018c614656565b61294c84600161469e565b81811061296957634e487b7160e01b600052603260045260246000fd5b905060200201602081019061297e9190613f1d565b90506129f8565b600161299460608d018d614656565b61299f9291506146f5565b82106129ab57886129f5565b6129b860608c018c614656565b6129c384600161469e565b8181106129e057634e487b7160e01b600052603260045260246000fd5b90506020020160208101906129f59190613f1d565b90505b612a0560408c018c614656565b612a1084600161469e565b818110612a2d57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612a429190613f1d565b6040516370a0823160e01b81526001600160a01b03838116600483015291909116906370a082319060240160206040518083038186803b158015612a8557600080fd5b505afa158015612a99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abd9190614241565b83600081518110612ade57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152612af660608c018c614656565b83818110612b1457634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612b299190613f1d565b6001600160a01b031663eab90da66000808e8060400190612b4a9190614656565b87818110612b6857634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612b7d9190613f1d565b8f8060400190612b8d9190614656565b612b9889600161469e565b818110612bb557634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612bca9190613f1d565b6040516001600160e01b031960e087901b168152600481019490945260248401929092526001600160a01b03908116604484015290811660648301528416608482015260a401600060405180830381600087803b158015612c2a57600080fd5b505af1158015612c3e573d6000803e3d6000fd5b5060019250612c5391505060608d018d614656565b612c5e9291506146f5565b821415612df957600083600081518110612c8857634e487b7160e01b600052603260045260246000fd5b60200260200101518c8060400190612ca09190614656565b612cab86600161469e565b818110612cc857634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612cdd9190613f1d565b6040516370a0823160e01b81526001600160a01b03858116600483015291909116906370a082319060240160206040518083038186803b158015612d2057600080fd5b505afa158015612d34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d589190614241565b612d6291906146f5565b90508b60200135811015612dc95760405162461bcd60e51b815260206004820152602860248201527f417661626f74526f757465723a20496e73756666696369656e74206f757470756044820152671d08185b5bdd5b9d60c21b60648201526084016109b0565b8084600181518110612deb57634e487b7160e01b600052603260045260246000fd5b602002602001018181525050505b5080612e048161474f565b915050612861565b50600080871180612e1f57506000600154115b15613053576001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216612e5b60408c018c614656565b6001612e6a60408f018f614656565b612e759291506146f5565b818110612e9257634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612ea79190613f1d565b6001600160a01b0316141561302357612ee882600181518110612eda57634e487b7160e01b600052603260045260246000fd5b602002602001015188613a6d565b90508960200135811015612f4f5760405162461bcd60e51b815260206004820152602860248201527f417661626f74526f757465723a20496e73756666696369656e74206f757470756044820152671d08185b5bdd5b9d60c21b60648201526084016109b0565b33612f5d60408c018c614656565b6001612f6c60408f018f614656565b612f779291506146f5565b818110612f9457634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612fa99190613f1d565b6001600160a01b03167fe6cdb6e1f794aa8f4cd0ecfaa3049c808c84128ff20f1d9fb6958809d32e51ef878486600181518110612ff657634e487b7160e01b600052603260045260246000fd5b602002602001015161300891906146f5565b60405161301692919061459a565b60405180910390a361307f565b8160018151811061304457634e487b7160e01b600052603260045260246000fd5b6020026020010151905061307f565b8160018151811061307457634e487b7160e01b600052603260045260246000fd5b602002602001015190505b6001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2166130b660408c018c614656565b60016130c560408f018f614656565b6130d09291506146f5565b8181106130ed57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906131029190613f1d565b6001600160a01b031614801561312157506001600160a01b0388163014155b1561319757613197888261313860408e018e614656565b60018f806040019061314a9190614656565b6131559291506146f5565b81811061317257634e487b7160e01b600052603260045260246000fd5b90506020020160208101906131879190613f1d565b6001600160a01b031691906134c6565b6131a460408b018b614656565b60016131b360408e018e614656565b6131be9291506146f5565b8181106131db57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906131f09190613f1d565b6001600160a01b031661320660408c018c614656565b600081811061322557634e487b7160e01b600052603260045260246000fd5b905060200201602081019061323a9190613f1d565b604080518d358152602081018590523381830152606081018b905290516001600160a01b0392909216917f361ceb771316054c3316cb5ecd6c9fa73d64cf7ff4248052cb4df39178a6ec729181900360800190a39998505050505050505050565b6040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561331657600080fd5b505af115801561332a573d6000803e3d6000fd5b5050505050565b306001600160a01b03821614610bc1576001600160a01b03831661338b576040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015613385573d6000803e3d6000fd5b50505050565b610bc16001600160a01b03841682846134c6565b610f398133613b27565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610d1f576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556134033390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610d1f576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6040516001600160a01b038316602482015260448101829052610bc19084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611e2f565b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561356a57600080fd5b505af1158015610b94573d6000803e3d6000fd5b60025433906001600160a01b03168114610f39576040517fd7af094e0000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016109b0565b600080836001600160a01b0316836040516135ea91906144a8565b6000604051808303816000865af19150503d8060008114613627576040519150601f19603f3d011682016040523d82523d6000602084013e61362c565b606091505b50915091508161367e5760405162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656460448201526064016109b0565b80511561338557808060200190518101906136999190614099565b6133855760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016109b0565b60408051602080825281830190925260609160208201818036833750505060208101929092525090565b6137606040518060800160405280606081526020016060815260200160608152602001600081525090565b604051806080016040528083600001518152602001836020015181526020018360400151815260200183606001518152509050919050565b84604001516137af836001600160a01b031661370b565b6040516020016137c09291906144c4565b60408051601f1981840301815291815286015260208501516137ea6001600160a01b03851661370b565b6040516020016137fb9291906144c4565b60408051601f198184030181529190526020860152845161381b8561370b565b60405160200161382c9291906144c4565b60408051601f19818403018152919052855260608501805182919061385290839061469e565b9052505050505050565b6040810151805160009161092791613918565b60408101515181516000916109279190613918565b60606020825161389491906146b6565b67ffffffffffffffff8111156138ba57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156138e3578160200160208202803683370190505b50905060005b602083516138f791906146b6565b81101561395a5761391d8361390d8360206146d6565b61391890602061469e565b015190565b82828151811061393d57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152806139528161474f565b9150506138e9565b50919050565b60606020825161397091906146b6565b67ffffffffffffffff81111561399657634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156139bf578160200160208202803683370190505b50905060005b602083516139d391906146b6565b81101561395a576139e98361390d8360206146d6565b828281518110613a0957634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280613a2b8161474f565b9150506139c5565b42811015610f39576040517fa83116fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600154821015613ac15760405162461bcd60e51b815260206004820152601e60248201527f417661626f74526f757465723a20496e73756666696369656e7420666565000060448201526064016109b0565b612710613ace83826146f5565b613ad890856146d6565b613ae291906146b6565b9392505050565b6001600160a01b0383163014613b1357613b0e6001600160a01b038516848484613ba5565b613385565b6133856001600160a01b03851683836134c6565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610d1f57613b63816001600160a01b03166014613bf6565b613b6e836020613bf6565b604051602001613b7f9291906144f3565b60408051601f198184030181529082905262461bcd60e51b82526109b091600401614587565b6040516001600160a01b03808516602483015283166044820152606481018290526133859085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611e2f565b60606000613c058360026146d6565b613c1090600261469e565b67ffffffffffffffff811115613c3657634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613c60576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110613ca557634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110613cfe57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000613d228460026146d6565b613d2d90600161469e565b90505b6001811115613dce577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613d7c57634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110613da057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93613dc781614738565b9050613d30565b508315613ae25760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109b0565b828054828255906000526020600020908101928215613e7f579160200282015b82811115613e7f578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e3d565b50613e8b929150613e8f565b5090565b5b80821115613e8b5760008155600101613e90565b8035613eaf816147b6565b919050565b60008083601f840112613ec5578182fd5b50813567ffffffffffffffff811115613edc578182fd5b602083019150836020828501011115613ef457600080fd5b9250929050565b60006080828403121561395a578081fd5b803560ff81168114613eaf57600080fd5b600060208284031215613f2e578081fd5b8135613ae2816147b6565b600060208284031215613f4a578081fd5b8151613ae2816147b6565b60008060408385031215613f67578081fd5b8235613f72816147b6565b946020939093013593505050565b600080600060608486031215613f94578081fd5b8335613f9f816147b6565b92506020840135613faf816147b6565b929592945050506040919091013590565b60008060408385031215613f67578182fd5b60006020808385031215613fe4578182fd5b823567ffffffffffffffff80821115613ffb578384fd5b818501915085601f83011261400e578384fd5b813581811115614020576140206147a0565b8060051b604051601f19603f83011681018181108582111715614045576140456147a0565b604052828152858101935084860182860187018a1015614063578788fd5b8795505b8386101561408c5761407881613ea4565b855260019590950194938601938601614067565b5098975050505050505050565b6000602082840312156140aa578081fd5b81518015158114613ae2578182fd5b6000602082840312156140ca578081fd5b5035919050565b600080604083850312156140e3578182fd5b8235915060208301356140f5816147b6565b809150509250929050565b600060208284031215614111578081fd5b81356001600160e01b031981168114613ae2578182fd5b60008060008060006080868803121561413f578081fd5b853567ffffffffffffffff80821115614156578283fd5b61416289838a01613efb565b965060208801359550604088013594506060880135915080821115614185578283fd5b5061419288828901613eb4565b969995985093965092949392505050565b60008060008060008060008060e0898b0312156141be578283fd5b883567ffffffffffffffff808211156141d5578485fd5b6141e18c838d01613efb565b995060208b0135985060408b0135975060608b0135915080821115614204578485fd5b506142118b828c01613eb4565b9096509450614224905060808a01613f0c565b925060a0890135915060c089013590509295985092959890939650565b600060208284031215614252578081fd5b5051919050565b60008060006060848603121561426d578081fd5b83359250602084013561427f816147b6565b9150604084013561428f816147b6565b809150509250925092565b6000806000806000608086880312156142b1578283fd5b8535945060208601356142c3816147b6565b935060408601356142d3816147b6565b9250606086013567ffffffffffffffff808211156142ef578283fd5b818801915088601f830112614302578283fd5b813581811115614310578384fd5b8960208260051b8501011115614324578384fd5b9699959850939650602001949392505050565b6000806000806080858703121561434c578182fd5b84359350602085013561435e816147b6565b9250604085013561436e816147b6565b9396929550929360600135925050565b600080600080600060a08688031215614395578283fd5b8535945060208601356143a7816147b6565b935060408601356143b7816147b6565b94979396509394606081013594506080013592915050565b600080600080608085870312156143e4578182fd5b8435935060208501356143f6816147b6565b92506040850135614406816147b6565b915061441460608601613f0c565b905092959194509250565b600060208284031215614430578081fd5b613ae282613f0c565b6000815180845260208085019450808401835b838110156144715781516001600160a01b03168752958201959082019060010161444c565b509495945050505050565b6000815180845261449481602086016020860161470c565b601f01601f19169290920160200192915050565b600082516144ba81846020870161470c565b9190910192915050565b600083516144d681846020880161470c565b8351908301906144ea81836020880161470c565b01949350505050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161452b81601785016020880161470c565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000601791840191820152835161456881602884016020880161470c565b01602801949350505050565b602081526000613ae26020830184614439565b602081526000613ae2602083018461447c565b6040815260006145ad604083018561447c565b90508260208301529392505050565b60208082528251608083830152805160a0840181905260009291820190839060c08601905b8083101561460157835182529284019260019290920191908401906145e1565b50838701519350601f199250828682030160408701526146218185614439565b9350505060408501518185840301606086015261463e8382614439565b92505050606084015160808401528091505092915050565b6000808335601e1984360301811261466c578283fd5b83018035915067ffffffffffffffff821115614686578283fd5b6020019150600581901b3603821315613ef457600080fd5b600082198211156146b1576146b161478a565b500190565b6000826146d157634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156146f0576146f061478a565b500290565b6000828210156147075761470761478a565b500390565b60005b8381101561472757818101518382015260200161470f565b838111156133855750506000910152565b6000816147475761474761478a565b506000190190565b60006000198214156147635761476361478a565b5060010190565b600060ff821660ff8114156147815761478161478a565b60010192915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610f3957600080fdfea2646970667358221220ad6740f747a1a00a36f8954b4a203d529f7f34ef9ff2772d1851629c54e4c71f64736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000063817b3683c2477398129c54d44682cd7a86b9db000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000200000000000000000000000008d06e6d98d757f5128c12e8c9a0ecdad825b0b20000000000000000000000006734503b71c4b004513512709fc547f6de2c08600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
-----Decoded View---------------
Arg [0] : _adapters (address[]): 0x08D06e6D98D757f5128c12e8c9a0ecDAD825b0b2,0x6734503B71c4b004513512709fc547f6de2c0860
Arg [1] : _trustedTokens (address[]): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [2] : _feeClaimer (address): 0x63817b3683c2477398129C54d44682cD7A86b9db
Arg [3] : _wrapped_native (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 00000000000000000000000063817b3683c2477398129c54d44682cd7a86b9db
Arg [3] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [5] : 00000000000000000000000008d06e6d98d757f5128c12e8c9a0ecdad825b0b2
Arg [6] : 0000000000000000000000006734503b71c4b004513512709fc547f6de2c0860
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [8] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
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.