Multichain Info
Latest 25 from a total of 298,219 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Swap No Split | 32741368 | 16 hrs ago | IN | 0 APE | 0.038383 | ||||
| Swap No Split | 32741335 | 16 hrs ago | IN | 0 APE | 0.03837914 | ||||
| Swap No Split | 32741215 | 16 hrs ago | IN | 0 APE | 0.03890575 | ||||
| Swap No Split | 32741134 | 16 hrs ago | IN | 0 APE | 0.03862246 | ||||
| Swap No Split | 32741131 | 16 hrs ago | IN | 0 APE | 0.03906743 | ||||
| Swap No Split | 32739870 | 17 hrs ago | IN | 0 APE | 0.03862775 | ||||
| Swap No Split | 32739808 | 17 hrs ago | IN | 0 APE | 0.03935193 | ||||
| Swap No Split | 32739542 | 17 hrs ago | IN | 0 APE | 0.03847523 | ||||
| Swap No Split | 32738253 | 18 hrs ago | IN | 0 APE | 0.03769339 | ||||
| Swap No Split | 32737539 | 18 hrs ago | IN | 0 APE | 0.03845916 | ||||
| Swap No Split | 32736309 | 19 hrs ago | IN | 0 APE | 0.03778877 | ||||
| Swap No Split | 32736300 | 19 hrs ago | IN | 0 APE | 0.03810978 | ||||
| Swap No Split | 32736294 | 19 hrs ago | IN | 0 APE | 0.03754361 | ||||
| Swap No Split | 32736100 | 19 hrs ago | IN | 0 APE | 0.0387394 | ||||
| Swap No Split | 32734926 | 19 hrs ago | IN | 0 APE | 0.03821543 | ||||
| Swap No Split | 32734820 | 19 hrs ago | IN | 0 APE | 0.03766746 | ||||
| Swap No Split | 32734650 | 19 hrs ago | IN | 0 APE | 0.0377606 | ||||
| Swap No Split | 32733568 | 20 hrs ago | IN | 0 APE | 0.03766644 | ||||
| Swap No Split | 32733245 | 20 hrs ago | IN | 0 APE | 0.0377608 | ||||
| Swap No Split | 32732171 | 21 hrs ago | IN | 0 APE | 0.0384799 | ||||
| Swap No Split | 32732083 | 21 hrs ago | IN | 0 APE | 0.03838697 | ||||
| Swap No Split | 32731345 | 21 hrs ago | IN | 0 APE | 0.03824105 | ||||
| Swap No Split | 32731302 | 21 hrs ago | IN | 0 APE | 0.03824085 | ||||
| Swap No Split | 32731050 | 21 hrs ago | IN | 0 APE | 0.03876624 | ||||
| Swap No Split | 32720438 | 29 hrs ago | IN | 0 APE | 0.03833897 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 25756810 | 86 days ago | 45 APE | ||||
| 25739798 | 86 days ago | 207.78126418 APE | ||||
| 25739798 | 86 days ago | 207.78126418 APE | ||||
| 25619592 | 88 days ago | 50 APE | ||||
| 25613065 | 88 days ago | 10 APE | ||||
| 25612882 | 88 days ago | 21.27561946 APE | ||||
| 25612882 | 88 days ago | 21.27561946 APE | ||||
| 25612871 | 88 days ago | 21.4 APE | ||||
| 25612843 | 88 days ago | 21.17125231 APE | ||||
| 25612843 | 88 days ago | 21.17125231 APE | ||||
| 25612837 | 88 days ago | 21.3 APE | ||||
| 25612824 | 88 days ago | 21.08429885 APE | ||||
| 25612824 | 88 days ago | 21.08429885 APE | ||||
| 25612812 | 88 days ago | 21.2 APE | ||||
| 25608444 | 88 days ago | 88 APE | ||||
| 25590923 | 88 days ago | 5.00421089 APE | ||||
| 25590923 | 88 days ago | 5.00421089 APE | ||||
| 25583341 | 89 days ago | 700 APE | ||||
| 25578238 | 89 days ago | 0.60951336 APE | ||||
| 25578238 | 89 days ago | 0.60951336 APE | ||||
| 25573860 | 89 days ago | 4.96779864 APE | ||||
| 25573860 | 89 days ago | 4.96779864 APE | ||||
| 25573849 | 89 days ago | 5 APE | ||||
| 25573836 | 89 days ago | 4.96982573 APE | ||||
| 25573836 | 89 days ago | 4.96982573 APE |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// ╟╗ ╔╬
// ╞╬╬ ╬╠╬
// ╔╣╬╬╬ ╠╠╠╠╦
// ╬╬╬╬╬╩ ╘╠╠╠╠╬
// ║╬╬╬╬╬ ╘╠╠╠╠╬
// ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╬╬╬╬╬╬╬╜ ╠╠╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╠
// ╙╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╕ ╬╬╬╬╬╬╬╜ ╣╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╩
// ╙╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╔╬╬╬╬╬╬╬ ╔╠╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬╬╬╬╬╠╠╠╠╝╙
// ╘╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╠╠╠╬╠╬╩╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╣╬╬╬╬╬╬╬╙
// ╣╬╬╬╬╬╬╬╬╬╬╠╣ ╣╬╠╠╠╬╩ ╚╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╣╬╬╬╬╬╬╬╬╬╣ ╣╬╠╠╠╬╬ ╣╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╟╬╬╬╬╬╬╬╩ ╬╬╠╠╠╠╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╠╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╒╬╬╠╠╬╠╠╬╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╬╬╬╠╠╠╠╝╝╝╝╝╝╝╠╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╚╬╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╣╬╬╬╬╠╠╩ ╘╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╙╬╬╬╬╬╬╬╬
//
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.17;
pragma experimental ABIEncoderV2;
import "./interface/IYakRouter.sol";
import "./interface/IAdapter.sol";
import "./interface/IERC20.sol";
import "./interface/IWETH.sol";
import "./lib/SafeERC20.sol";
import "./lib/Maintainable.sol";
import "./lib/YakViewUtils.sol";
import "./lib/Recoverable.sol";
import "./lib/SafeERC20.sol";
contract CamelotYakRouter is Maintainable, Recoverable, IYakRouter {
using SafeERC20 for IERC20;
using OfferUtils for Offer;
address public immutable WNATIVE;
address public constant NATIVE = address(0);
string public constant NAME = "CamelotYakRouter";
uint256 public constant FEE_DENOMINATOR = 1e4;
uint256 public MIN_FEE = 0;
address public FEE_CLAIMER;
address[] public TRUSTED_TOKENS;
address[] public ADAPTERS;
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) override public onlyMaintainer {
emit UpdatedTrustedTokens(_trustedTokens);
TRUSTED_TOKENS = _trustedTokens;
}
function setAdapters(address[] memory _adapters) override public onlyMaintainer {
emit UpdatedAdapters(_adapters);
ADAPTERS = _adapters;
}
function setMinFee(uint256 _fee) override external onlyMaintainer {
emit UpdatedMinFee(MIN_FEE, _fee);
MIN_FEE = _fee;
}
function setFeeClaimer(address _claimer) override public onlyMaintainer {
emit UpdatedFeeClaimer(FEE_CLAIMER, _claimer);
FEE_CLAIMER = _claimer;
}
// -- GENERAL --
function trustedTokensCount() override external view returns (uint256) {
return TRUSTED_TOKENS.length;
}
function adaptersCount() override external view returns (uint256) {
return ADAPTERS.length;
}
// Fallback
receive() external payable {}
// -- HELPERS --
function _applyFee(uint256 _amountIn, uint256 _fee) internal view returns (uint256) {
require(_fee >= MIN_FEE, "YakRouter: 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, uint _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
) override external view returns (uint256, address) {
IAdapter _adapter = IAdapter(ADAPTERS[_index]);
try IAdapter(_adapter).query(_amountIn, _tokenIn, _tokenOut) returns (uint256 _amountOut, address _recipient) {
return (_amountOut, _recipient);
}
catch { return (0, address(0)); }
}
/**
* Query specified adapters
*/
function queryNoSplit(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
uint8[] calldata _options
) override public view returns (Query memory) {
Query memory bestQuery;
for (uint8 i; i < _options.length; i++) {
address _adapter = ADAPTERS[_options[i]];
try IAdapter(_adapter).query(_amountIn, _tokenIn, _tokenOut) returns (uint256 amountOut, address _recipient) {
if (i == 0 || amountOut > bestQuery.amountOut) {
bestQuery = Query(_adapter, _recipient, _tokenIn, _tokenOut, amountOut);
}
}
catch { continue; }
}
return bestQuery;
}
/**
* Query all adapters
*/
function queryNoSplit(
uint256 _amountIn,
address _tokenIn,
address _tokenOut
) override public view returns (Query memory) {
Query memory bestQuery;
for (uint8 i; i < ADAPTERS.length; i++) {
address _adapter = ADAPTERS[i];
try IAdapter(_adapter).query(_amountIn, _tokenIn, _tokenOut) returns (uint256 amountOut, address _recipient) {
if (i == 0 || amountOut > bestQuery.amountOut) {
bestQuery = Query(_adapter, _recipient, _tokenIn, _tokenOut, amountOut);
}
}
catch { continue; }
}
return bestQuery;
}
/**
* Return path with best returns between two tokens
* Takes gas-cost into account
*/
function findBestPathWithGas(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
address[] memory _trustedTokens,
uint256 _maxSteps,
uint256 _gasPrice
) override external view returns (FormattedOffer memory) {
require(_maxSteps > 0 && _maxSteps < 5, "YakRouter: Invalid max-steps");
Offer memory queries = OfferUtils.newOffer(_amountIn, _tokenIn);
uint256 gasPriceInExitTkn = _gasPrice > 0 ? getGasPriceInExitTkn(_gasPrice, _tokenOut) : 0;
uint256 ttLength = TRUSTED_TOKENS.length;
// Concatenate default and additional trusted tokens
address[] memory _allTrustedTokens = new address[](
ttLength + _trustedTokens.length
);
for (uint i = 0; i < ttLength; ) {
_allTrustedTokens[i] = TRUSTED_TOKENS[i];
unchecked {
i++;
}
}
for (uint i = 0; i < _trustedTokens.length; ) {
_allTrustedTokens[ttLength + i] = _trustedTokens[i];
unchecked {
i++;
}
}
queries = _findBestPath(_amountIn, _tokenIn, _tokenOut, _allTrustedTokens, _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)
address[] memory _trustedTokens;
FormattedOffer memory gasQuery = findBestPath(1e18, WNATIVE, _tokenOut, _trustedTokens, 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,
address[] memory _trustedTokens,
uint256 _maxSteps
) override public view returns (FormattedOffer memory) {
require(_maxSteps > 0 && _maxSteps < 5, "YakRouter: Invalid max-steps");
Offer memory queries = OfferUtils.newOffer(_amountIn, _tokenIn);
uint256 ttLength = TRUSTED_TOKENS.length;
// Concatenate default and additional trusted tokens
address[] memory _allTrustedTokens = new address[](
ttLength + _trustedTokens.length
);
for (uint i = 0; i < ttLength; ) {
_allTrustedTokens[i] = TRUSTED_TOKENS[i];
unchecked {
i++;
}
}
for (uint i = 0; i < _trustedTokens.length; ) {
_allTrustedTokens[ttLength + i] = _trustedTokens[i];
unchecked {
i++;
}
}
queries = _findBestPath(_amountIn, _tokenIn, _tokenOut, _allTrustedTokens, _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,
address[] memory _trustedTokens,
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.recipient, 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 < _trustedTokens.length; ) {
if (_tokenIn == _trustedTokens[i]) {
unchecked {
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, _trustedTokens[i]);
if (bestSwap.amountOut == 0) {
unchecked {
i++;
}
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.recipient, bestSwap.tokenOut, gasEstimate);
newOffer = _findBestPath(
bestSwap.amountOut,
_trustedTokens[i],
_tokenOut,
_trustedTokens,
_maxSteps,
newOffer,
_tknOutPriceNwei
); // Recursive step
// Check that the last token in the path is the tokenOut and update the new best option if neccesary
if (
_tokenOut == newOffer.getTokenOut() &&
newOffer.getAmountOut() > bestAmountOut
) {
if (newOffer.gasEstimate > bestOption.gasEstimate) {
uint256 gasCostDiff = (_tknOutPriceNwei * (newOffer.gasEstimate - bestOption.gasEstimate)) /
1e9;
if (
gasCostDiff >
newOffer.getAmountOut() - bestAmountOut
) {
unchecked {
i++;
}
continue;
}
}
bestAmountOut = newOffer.getAmountOut();
bestOption = newOffer;
}
unchecked {
i++;
}
}
}
return bestOption;
}
// -- SWAPPERS --
function _swapNoSplit(
Trade calldata _trade,
address _from,
uint256 _fee,
address _to
) internal returns (uint256) {
uint256 amountIn = _trade.amountIn;
if (_fee > 0 || MIN_FEE > 0) {
// Transfer fees to the claimer account and decrease initial amount
amountIn = _applyFee(_trade.amountIn, _fee);
_transferFrom(_trade.path[0], _from, FEE_CLAIMER, _trade.amountIn - amountIn);
}
uint256 recipientBalanceBefore = IERC20(_trade.path[0]).balanceOf(_trade.recipients[0]);
_transferFrom(_trade.path[0], _from, _trade.recipients[0], amountIn);
amountIn = IERC20(_trade.path[0]).balanceOf(_trade.recipients[0]) - recipientBalanceBefore;
address tokenOut = _trade.path[_trade.path.length - 1];
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 = i < _trade.adapters.length - 1 ? _trade.recipients[i + 1] : _to;
recipientBalanceBefore = IERC20(_trade.path[i + 1]).balanceOf(targetAddress);
IAdapter(_trade.adapters[i]).swap(
amountIn,
0,
_trade.path[i],
_trade.path[i + 1],
targetAddress
);
amountIn = IERC20(_trade.path[i + 1]).balanceOf(targetAddress) - recipientBalanceBefore;
}
uint256 amountOut = amountIn;
require(amountOut >= _trade.amountOut, "YakRouter: Insufficient output amount");
emit YakSwap(_trade.path[0], tokenOut, _trade.amountIn, amountOut);
return amountOut;
}
function swapNoSplit(
Trade calldata _trade,
uint256 _fee,
address _to
) override public {
_swapNoSplit(_trade, msg.sender, _fee, _to);
}
function swapNoSplitFromETH(
Trade calldata _trade,
uint256 _fee,
address _to
) override external payable {
require(_trade.path[0] == WNATIVE, "YakRouter: Path needs to begin with WETH");
_wrap(_trade.amountIn);
_swapNoSplit(_trade, address(this), _fee, _to);
}
function swapNoSplitToETH(
Trade calldata _trade,
uint256 _fee,
address _to
) override public {
require(_trade.path[_trade.path.length - 1] == WNATIVE, "YakRouter: Path needs to end with WETH");
uint256 returnAmount = _swapNoSplit(_trade, msg.sender, _fee, address(this));
_unwrap(returnAmount);
_returnTokensTo(NATIVE, returnAmount, _to);
}
/**
* Swap token to token without the need to approve the first token
*/
function swapNoSplitWithPermit(
Trade calldata _trade,
uint256 _fee,
address _to,
uint256 _deadline,
uint8 _v,
bytes32 _r,
bytes32 _s
) override external {
IERC20(_trade.path[0]).permit(msg.sender, address(this), _trade.amountIn, _deadline, _v, _r, _s);
swapNoSplit(_trade, _fee, _to);
}
/**
* Swap token to WETH without the need to approve the first token
*/
function swapNoSplitToETHWithPermit(
Trade calldata _trade,
uint256 _fee,
address _to,
uint256 _deadline,
uint8 _v,
bytes32 _r,
bytes32 _s
) override external {
IERC20(_trade.path[0]).permit(msg.sender, address(this), _trade.amountIn, _deadline, _v, _r, _s);
swapNoSplitToETH(_trade, _fee, _to);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => 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(account),
" 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 (last updated v4.9.4) (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;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// 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.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _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) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @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] = _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);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IAdapter {
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, address);
}// 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;
import "./IERC20.sol";
interface IWETH is IERC20 {
function withdraw(uint256 amount) external;
function deposit() external payable;
}// ╟╗ ╔╬
// ╞╬╬ ╬╠╬
// ╔╣╬╬╬ ╠╠╠╠╦
// ╬╬╬╬╬╩ ╘╠╠╠╠╬
// ║╬╬╬╬╬ ╘╠╠╠╠╬
// ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╬╬╬╬╬╬╬╜ ╠╠╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╠
// ╙╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╕ ╬╬╬╬╬╬╬╜ ╣╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╩
// ╙╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╔╬╬╬╬╬╬╬ ╔╠╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬╬╬╬╬╠╠╠╠╝╙
// ╘╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╠╠╠╬╠╬╩╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╣╬╬╬╬╬╬╬╙
// ╣╬╬╬╬╬╬╬╬╬╬╠╣ ╣╬╠╠╠╬╩ ╚╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╣╬╬╬╬╬╬╬╬╬╣ ╣╬╠╠╠╬╬ ╣╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╟╬╬╬╬╬╬╬╩ ╬╬╠╠╠╠╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╠╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╒╬╬╠╠╬╠╠╬╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╬╬╬╠╠╠╠╝╝╝╝╝╝╝╠╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╚╬╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╣╬╬╬╬╠╠╩ ╘╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╙╬╬╬╬╬╬╬╬
//
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
struct Query {
address adapter;
address recipient;
address tokenIn;
address tokenOut;
uint256 amountOut;
}
struct Offer {
bytes amounts;
bytes adapters;
bytes path;
bytes recipients;
uint256 gasEstimate;
}
struct FormattedOffer {
uint256[] amounts;
address[] adapters;
address[] path;
address[] recipients;
uint256 gasEstimate;
}
struct Trade {
uint256 amountIn;
uint256 amountOut;
address[] path;
address[] adapters;
address[] recipients;
}
interface IYakRouter {
event UpdatedTrustedTokens(address[] _newTrustedTokens);
event UpdatedAdapters(address[] _newAdapters);
event UpdatedMinFee(uint256 _oldMinFee, uint256 _newMinFee);
event UpdatedFeeClaimer(address _oldFeeClaimer, address _newFeeClaimer);
event YakSwap(address indexed _tokenIn, address indexed _tokenOut, uint256 _amountIn, uint256 _amountOut);
// 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, address);
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,
address[] memory _trustedTokens,
uint256 _maxSteps,
uint256 _gasPrice
) external view returns (FormattedOffer memory);
function findBestPath(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
address[] memory _trustedTokens,
uint256 _maxSteps
) external view returns (FormattedOffer memory);
// swap
function swapNoSplit(
Trade calldata _trade,
uint256 _fee,
address _to
) external;
function swapNoSplitFromETH(
Trade calldata _trade,
uint256 _fee,
address _to
) external payable;
function swapNoSplitToETH(
Trade calldata _trade,
uint256 _fee,
address _to
) external;
function swapNoSplitWithPermit(
Trade calldata _trade,
uint256 _fee,
address _to,
uint256 _deadline,
uint8 _v,
bytes32 _r,
bytes32 _s
) external;
function swapNoSplitToETHWithPermit(
Trade calldata _trade,
uint256 _fee,
address _to,
uint256 _deadline,
uint8 _v,
bytes32 _r,
bytes32 _s
) external;
}// 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);
}
}
}// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.4;
import { Offer, FormattedOffer } from "../interface/IYakRouter.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.recipients, _queries.gasEstimate);
}
/**
* Appends new elements to the end of Offer struct
*/
function addToTail(
Offer memory _queries,
uint256 _amount,
address _adapter,
address _recipient,
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.recipients = bytes.concat(_queries.recipients, _recipient.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.recipients.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,
address recipient,
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.recipients = bytes.concat(abi.encodePacked(offer.recipients), recipient.toBytes()).toAddresses();
offer.gasEstimate += gasEstimate;
}
/**
* Appends new elements to the beginning of FormattedOffer
*/
function addToHead(
FormattedOffer memory offer,
uint256 amountOut,
address wrapper,
address tokenOut,
address recipient,
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.path = bytes.concat(recipient.toBytes(), abi.encodePacked(offer.recipients)).toAddresses();
offer.gasEstimate += gasEstimate;
}
function getAmountOut(FormattedOffer memory offer) internal pure returns (uint256) {
return offer.amounts[offer.amounts.length - 1];
}
}{
"optimizer": {
"enabled": true,
"runs": 10000,
"details": {
"yulDetails": {
"optimizerSteps": "u"
}
}
},
"viaIR": true,
"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"},{"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"},{"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"}],"name":"YakSwap","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":"address[]","name":"_trustedTokens","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":"address[]","name":"recipients","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":"address[]","name":"_trustedTokens","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":"address[]","name":"recipients","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":"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"},{"internalType":"address","name":"","type":"address"}],"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":"recipient","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":"recipient","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":"address[]","name":"recipients","type":"address[]"}],"internalType":"struct Trade","name":"_trade","type":"tuple"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"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":"address[]","name":"recipients","type":"address[]"}],"internalType":"struct Trade","name":"_trade","type":"tuple"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"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":"address[]","name":"recipients","type":"address[]"}],"internalType":"struct Trade","name":"_trade","type":"tuple"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"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":"address[]","name":"recipients","type":"address[]"}],"internalType":"struct Trade","name":"_trade","type":"tuple"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"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":"address[]","name":"recipients","type":"address[]"}],"internalType":"struct Trade","name":"_trade","type":"tuple"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"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","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
60a06040523462000061575b620000236200001962000262565b92919091620002cb565b6040516142c962000cc18239608051818181610faa015281816127e60152818161365d015281816136af015281816137de015261383c01526142c990f35b6200006a600080fd5b6200000b565b600080fd5b50634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b03821117620000ae57604052565b620000b862000075565b604052565b90620000d4620000cc60405190565b92836200008c565b565b60209081906001600160401b038111620000ef57020190565b620000f962000075565b020190565b6001600160a01b031690565b90565b6001600160a01b0381165b036200007057565b90505190620000d4826200010d565b90929192620001486200014282620000d6565b620000bd565b93818552602080860192028301928184116200018b575b915b8383106200016f5750505050565b602080916200017f848662000120565b81520192019162000161565b62000194600080fd5b6200015f565b906200010a9181601f82011215620001b9575b6020815191016200012f565b620001c2600080fd5b620001ad565b60808183031262000253575b8051620001f59083906001600160401b03811162000244575b83016200019a565b926200010a6200021b84602085015160018060401b03811162000235575b85016200019a565b936200022b816040860162000120565b9360600162000120565b6200023e600080fd5b62000213565b6200024d600080fd5b620001ed565b6200025c600080fd5b620001d4565b6200028562004faa803803806200027981620000bd565b928339810190620001c8565b90919293565b90600019905b9181191691161790565b6200010a6200010a6200010a9290565b90620002bf6200010a620002c7926200029b565b82546200028b565b9055565b906200030f92620003036200030992620002e462000314565b620002f260006001620002ab565b620002fd876200052c565b62000769565b620008a9565b620007d0565b608052565b620000d4620000d46200032e565b6200010a60006200029b565b620000d43362000348816200034262000322565b62000359565b60008051602062004f8a8339815191525b90620000d491620003d2565b905b600052602052604060002090565b6200010a90620000fe906001600160a01b031682565b6200010a9062000375565b6200010a906200038b565b90620003679062000396565b9060ff9062000291565b90620003ca6200010a620002c792151590565b8254620003ad565b90620003e7620003e3828462000461565b1590565b620003f0575050565b6200041660016200041083600062000409878262000365565b01620003a1565b620003b7565b33906200045062000449620004497f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9590565b9262000396565b926200045b60405190565b600090a4565b6200010a916200047991620004096000918262000365565b5460ff1690565b0190565b156200048c57565b60405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b6064820152608490fd5b0390fd5b620000d490620005116200050b335b60008051602062004f8a83398151915262000461565b62000484565b620000d490620005218162000396565b6000199190620009b2565b620000d490620004e6565b620000d4906200054b6200050b33620004f5565b62000721565b90620005746200056d62000563845190565b8084529260200190565b9260200190565b9060005b818110620005865750505090565b909192620005ae620005a760019286516001600160a01b0316815260200190565b9460200190565b92910162000578565b60208082526200010a9291019062000551565b9160001960089290920291821b911b62000291565b9190620005f46200010a620002c7936200029b565b908354620005ca565b620000d491600091620005df565b81811062000617575050565b80620006276000600193620005fd565b016200060b565b90918281106200063d57505050565b620000d4929062000655905b92600052602060002090565b90810191016200060b565b90620000d49168010000000000000000821162000684575b8054908281556200062e565b6200068e62000075565b62000678565b6001620006c862000649620006a7855190565b94838060401b03861162000705575b620006c2868662000660565b60200190565b92049160005b838110620006dc5750505050565b6001906020620006f76200010a86516001600160a01b031690565b9401938184015501620006ce565b6200070f62000075565b620006b6565b90620000d49162000694565b620000d4907f658ff1688002926d8f426cb10c052ec29003f50042df9652d8613484c1a586476200075160405190565b806200075e8482620005b7565b0390a1600362000715565b620000d49062000537565b620000d490620007886200050b33620004f5565b620000d4907febf7325f48e05e5e38809c69f8b02a7c907ed31d8768e6c2d841b1296a9225fe620007b860405190565b80620007c58482620005b7565b0390a1600462000715565b620000d49062000774565b620000d490620007ef6200050b33620004f5565b62000852565b6200010a90620000fe565b6200010a9054620007f5565b6001600160a01b0391821681529116602082015260400190565b906001600160a01b039062000291565b906200084a6200010a620002c79262000396565b825462000826565b620000d49062000863600262000800565b817fb2c853ac4d80d18d058c43d8018d077a036e542a79acae1647f5ad2a8c76f4e2916200089e6200089460405190565b928392836200080c565b0390a1600262000836565b620000d490620007db565b8062000118565b90505190620000d482620008b4565b906200010a9160208183031215620008bb57620008e5600080fd5b620008bb565b506040513d6000823e3d90fd5b156200090057565b60405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608490fd5b62000987620009816200010a9263ffffffff1690565b60e01b90565b6001600160e01b03191690565b6001600160a01b039091168152604081019291620000d49160200152565b62000a2260049262000a12620000d495620009e7600084620009d4826200029b565b841491821562000a28575b5050620008f8565b620009f663095ea7b36200096b565b9262000a0160405190565b968794602086019081520162000994565b602082018103825203836200008c565b62000c50565b909150602062000a388962000396565b63dd62ed3e9062000a6962000a4d3062000396565b9262000a7562000a5c60405190565b9788958694859460e01b90565b8452600484016200080c565b03915afa91821562000ae9575b60009262000aa8575b5062000a9b62000a9f916200029b565b9190565b148438620009df565b62000a9f91925062000ad862000a9b9160203d811162000ae1575b62000acf81836200008c565b810190620008ca565b92915062000a8b565b503d62000ac3565b62000af3620008eb565b62000a82565b60209062000480906001600160401b03811162000b1a57601f01601f191690565b62000b2462000075565b601f01601f191690565b9062000b3e620001428362000af9565b918252565b3d1562000b605762000b553d62000b2e565b903d6000602084013e565b606090565b1562000b6d57565b60405162461bcd60e51b815280620004e2600482016020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b80151562000118565b90505190620000d48262000bb7565b906200010a916020818303121562000bc05762000bea600080fd5b62000bc0565b1562000bf857565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b60009162000c5f839262000396565b9082602082019151925af162000c7f62000c7862000b43565b9162000b65565b805162000c9162000a9b60006200029b565b1162000c9a5750565b62000cba81602062000cae620000d4945190565b81830101910162000bcf565b62000bf056fe6080604052600436101561001e575b361561001c5761001c600080fd5b005b60003560e01c8062b99e361461032957806301ffc9a714610320578063248a9ca3146103175780632f2ff15d1461030e57806331ac99201461030557806336568abe146102fc5780633a9a4081146102f35780633cf57ac7146102ea578063414cff85146102e157806352a52ab0146102d85780636b453c1f146102cf57806376c7a3c7146102c657806376ebe69c146102bd5780637c7a561b146102b4578063809356aa146102ab57806383637d14146102a25780638980f11f146102995780638bb9c5bf1461029057806391d148541461028757806392f5d88a1461027e578063952e901214610275578063a0cf0aea1461026c578063a217fddf14610263578063a3f4df7e1461025a578063aede369314610251578063b381cf4014610248578063b9a89ca31461023f578063befe980314610236578063c3accd481461022d578063c8a3a5c614610224578063ce6e28f21461021b578063d547741f14610212578063d73792a914610209578063d8baf7cf14610200578063dd8544b3146101f7578063dede7f15146101ee578063f2fde38b146101e5578063f6ee13a6146101dc5763f87422540361000e576101d7611424565b61000e565b506101d76113f3565b506101d7611344565b506101d7611319565b506101d76112bd565b506101d7611296565b506101d761126c565b506101d7611231565b506101d7611209565b506101d76111e2565b506101d76111bb565b506101d76111a6565b506101d761116c565b506101d7610f93565b506101d7610f6c565b506101d7610f36565b506101d7610e08565b506101d7610dbf565b506101d7610d6d565b506101d7610d27565b506101d7610bda565b506101d7610bb3565b506101d7610b8b565b506101d7610b32565b506101d7610a93565b506101d7610a06565b506101d76109db565b506101d76109b1565b506101d7610968565b506101d7610921565b506101d761085d565b506101d761082f565b506101d7610748565b506101d7610576565b506101d761054f565b506101d7610522565b506101d76104a0565b506101d7610434565b506101d76103a5565b600080fd5b600091031261034257565b61034a600080fd5b565b61036e916008021c5b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b9061036e915461034c565b61036e60006002610371565b61039190610355565b9052565b60208101929161034a9190610388565b50346103d2575b6103b7366004610337565b6103ce6103c261037c565b60405191829182610395565b0390f35b6103da600080fd5b6103ac565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b0361033257565b9050359061034a826103df565b9061036e916020818303121561040a5761042f600080fd5b61040a565b5034610463575b6103ce61045161044c366004610417565b61146c565b60405191829182901515815260200190565b61046b600080fd5b61043b565b80610403565b9050359061034a82610470565b9061036e91602081830312156104765761049b600080fd5b610476565b50346104ce575b6103ce6104bd6104b8366004610483565b61159c565b6040515b9182918290815260200190565b6104d6600080fd5b6104a7565b61040381610355565b9050359061034a826104db565b919061036e90604084820312610515575b61050c8185610476565b936020016104e4565b61051d600080fd5b610502565b5034610542575b61053d6105373660046104f1565b906115db565b604051005b61054a600080fd5b610529565b5034610569575b61053d610564366004610483565b611ff7565b610571600080fd5b610556565b5034610591575b61053d61058b3660046104f1565b906117a4565b610599600080fd5b61057d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810190811067ffffffffffffffff82111761063657604052565b61063e6105c6565b604052565b9061034a61065060405190565b92836105f6565b6020809167ffffffffffffffff811161066f57020190565b6106776105c6565b020190565b9092919261069161068c82610657565b610643565b93818552602080860192028301928184116106cf575b915b8383106106b65750505050565b602080916106c484866104e4565b8152019201916106a9565b6106d7600080fd5b6106a7565b9061036e9181601f820112156106f8575b60208135910161067c565b610700600080fd5b6106ed565b9061036e9160208183031261073b575b80359067ffffffffffffffff821161072e575b016106dc565b610736600080fd5b610728565b610743600080fd5b610715565b5034610762575b61053d61075d366004610705565b611f33565b61076a600080fd5b61074f565b908160a091031261077d5790565b61036e600080fd5b60ff8116610403565b9050359061034a82610785565b60e081830312610822575b6107c382823567ffffffffffffffff8111610815575b830161076f565b926107d18360208401610476565b926107df81604085016104e4565b926107ed8260608301610476565b9261036e6107fe846080850161078e565b9361080c8160a08601610476565b9360c001610476565b61081d600080fd5b6107bc565b61082a600080fd5b6107a6565b5034610850575b61053d61084436600461079b565b95949094939193613a25565b610858600080fd5b610836565b503461087e575b61053d61087236600461079b565b9594909493919361395a565b610886600080fd5b610864565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6108db6001916108c9815490565b8410156108e457600052602060002090565b91020190600090565b6108ec61088b565b600052602060002090565b60036000610903825490565b83101561091e575061036e91610918916108bb565b90610371565b80fd5b503461093e575b6103ce6103c2610939366004610483565b6108f7565b610946600080fd5b610928565b9061036e91602081830312156104e457610963600080fd5b6104e4565b5034610982575b61053d61097d36600461094b565b613a87565b61098a600080fd5b61096f565b61036e916008021c81565b9061036e915461098f565b61036e6000600161099a565b50346109ce575b6109c3366004610337565b6103ce6104bd6109a5565b6109d6600080fd5b6109b8565b50346109f9575b6109ed366004610337565b6103ce6104bd60035490565b610a01600080fd5b6109e2565b5034610a24575b610a18366004610337565b6103ce6104bd60045490565b610a2c600080fd5b610a0d565b608081830312610a6e575b610a468282610476565b9261036e610a5784602085016104e4565b93610a6581604086016104e4565b9360600161078e565b610a76600080fd5b610a3c565b90815260408101929161034a916020905b0190610388565b5034610ac7575b610ab1610aa8366004610a31565b92919091612148565b906103ce610abe60405190565b92839283610a7b565b610acf600080fd5b610a9a565b9091606082840312610b25575b61036e610b0184843567ffffffffffffffff8111610b18575b850161076f565b93610b0f8160208601610476565b936040016104e4565b610b20600080fd5b610afa565b610b2d600080fd5b610ae1565b5034610b4d575b61053d610b47366004610ad4565b916137a4565b610b55600080fd5b610b39565b919061036e90604084820312610b7e575b610b7581856104e4565b93602001610476565b610b86600080fd5b610b6b565b5034610ba6575b61053d610ba0366004610b5a565b90613bc9565b610bae600080fd5b610b92565b5034610bcd575b61053d610bc8366004610483565b613adb565b610bd5600080fd5b610bba565b5034610bf8575b6103ce610451610bf23660046104f1565b9061156c565b610c00600080fd5b610be1565b909182601f83011215610c44575b602082359267ffffffffffffffff8411610c37575b01926020830284011161034257565b610c3f600080fd5b610c28565b610c4c600080fd5b610c13565b608081830312610cb3575b610c668282610476565b92610ca2610c7784602085016104e4565b93610c8581604086016104e4565b9360608101359067ffffffffffffffff8211610ca6575b01610c05565b9091565b610cae600080fd5b610c9c565b610cbb600080fd5b610c5c565b9060808061034a93610cda60008201516000860190610388565b610cec60208201516020860190610388565b610cfe60408201516040860190610388565b610d1060608201516060860190610388565b0151910152565b60a08101929161034a9190610cc0565b5034610d54575b6103ce610d48610d3f366004610c51565b93929092612295565b60405191829182610d17565b610d5c600080fd5b610d2e565b60046000610903825490565b5034610d8a575b6103ce6103c2610d85366004610483565b610d61565b610d92600080fd5b610d74565b61035561036e61036e9290565b61036e90610d97565b61036e6000610da4565b61036e610dad565b5034610ddc575b610dd1366004610337565b6103ce6103c2610db7565b610de4600080fd5b610dc6565b61036e61036e61036e9290565b61036e6000610de9565b61036e610df6565b5034610e25575b610e1a366004610337565b6103ce6104bd610e00565b610e2d600080fd5b610e0f565b610e6f60209167ffffffffffffffff8111610e7357601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690565b0190565b61059e6105c6565b90610e8861068c83610e32565b918252565b610e976010610e7b565b7f43616d656c6f7459616b526f7574657200000000000000000000000000000000602082015290565b61036e610e8d565b61036e610ec0565b61036e610ec8565b60005b838110610eeb5750506000910152565b8181015183820152602001610edb565b610f1c61059e602093610e6f93610f10815190565b80835293849260200190565b95869101610ed8565b602080825261036e92910190610efb565b5034610f5f575b610f48366004610337565b6103ce610f53610ed0565b60405191829182610f25565b610f67600080fd5b610f3d565b5034610f86575b61053d610f81366004610483565b613c2e565b610f8e600080fd5b610f73565b5034610fce575b610fa5366004610337565b6103ce7f00000000000000000000000000000000000000000000000000000000000000006103c2565b610fd6600080fd5b610f9a565b919060a083820312611048575b610ff28184610476565b9261100082602083016104e4565b9261036e61101184604085016104e4565b9361103281606086013567ffffffffffffffff811161103b575b86016106dc565b93608001610476565b611043600080fd5b61102b565b611050600080fd5b610fe8565b9061107561106e611064845190565b8084529260200190565b9260200190565b9060005b8181106110865750505090565b9091926110a361109c6001928651815260200190565b9460200190565b929101611079565b90610e6f81602093610388565b906110c761106e611064845190565b9060005b8181106110d85750505090565b9091926110eb61109c60019286516110ab565b9291016110cb565b9061036e9060808061115361114161112f61111d60a0870160008a015188820360008a0152611055565b602089015187820360208901526110b8565b604088015186820360408801526110b8565b606087015185820360608701526110b8565b940151910152565b602080825261036e929101906110f3565b5034611199575b6103ce61118d611184366004610fdb565b9392909261288d565b6040519182918261115b565b6111a1600080fd5b611173565b5061053d6111b5366004610ad4565b91613625565b50346111d5575b61053d6111d036600461094b565b6120c6565b6111dd600080fd5b6111c2565b50346111fc575b61053d6111f7366004610705565b611ed7565b611204600080fd5b6111e9565b5034611224575b61053d61121e366004610ad4565b91612e11565b61122c600080fd5b611210565b503461124c575b61053d6112463660046104f1565b90611728565b611254600080fd5b611238565b61036e612710610de9565b61036e611259565b5034611289575b61127e366004610337565b6103ce6104bd611264565b611291600080fd5b611273565b50346112b0575b61053d6112ab36600461094b565b613ab1565b6112b8600080fd5b61129d565b50346112d7575b61053d6112d236600461094b565b611ccf565b6112df600080fd5b6112c4565b909160608284031261130c575b61036e6112fe8484610476565b93610b0f81602086016104e4565b611314600080fd5b6112f1565b5034611337575b6103ce610d486113313660046112e4565b916123f9565b61133f600080fd5b611320565b503461135e575b61053d61135936600461094b565b613ae5565b611366600080fd5b61134b565b909160c0828403126113e6575b6113828383610476565b9261139081602085016104e4565b9261139e82604083016104e4565b9261036e6113c284606085013567ffffffffffffffff81116113d9575b85016106dc565b936113d08160808601610476565b9360a001610476565b6113e1600080fd5b6113bb565b6113ee600080fd5b611378565b5034611417575b6103ce61118d61140b36600461136b565b949390939291926125e8565b61141f600080fd5b6113fa565b503461145f575b611436366004610337565b6103ce7f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab956104bd565b611467600080fd5b61142b565b7f7965db0b000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216149081156114bc575090565b61036e91507fffffffff00000000000000000000000000000000000000000000000000000000167f01ffc9a7000000000000000000000000000000000000000000000000000000001490565b905b600052602052604060002090565b61035561036e61036e9273ffffffffffffffffffffffffffffffffffffffff1690565b61036e90611518565b61036e9061153b565b9061150a90611544565b61036e905b60ff1690565b61036e9054611557565b61036e916115869161158060009182611508565b0161154d565b611562565b61036e9081565b61036e905461158b565b60016115b561036e926115ad600090565b506000611508565b01611592565b9061034a916115d16115cc8261159c565b6115e5565b9061034a916117f8565b9061034a916115bb565b61034a903390611681565b61036e90610de9565b610e6f6116119260209261160b815190565b94859290565b93849101610ed8565b61165861036e9392611652611652937f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260170190565b906115f9565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000815260110190565b9061169361168f828461156c565b1590565b61169b575050565b6117099161036e6116b76116b16116f194611bc4565b926115f0565b6116cc6020916116c683610de9565b90611a2a565b926116e56116d960405190565b9485938401928361161a565b908103825203826105f6565b60405191829162461bcd60e51b835260048301610f25565b0390fd5b9061034a9161171e6115cc8261159c565b9061034a9161186e565b9061034a9161170d565b1561173957565b60405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608490fd5b61034a91906117c96117ba33610355565b610355565b6117c384610355565b14611732565b61186e565b9060ff905b9181191691161790565b906117ed61036e6117f492151590565b82546117ce565b9055565b9061180661168f828461156c565b61180e575050565b61182860016118238360006115808782611508565b6117dd565b339061185e6118586118587f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9590565b92611544565b9261186860405190565b600090a4565b90611879818361156c565b611881575050565b611895600061182383826115808782611508565b339061185e6118586118587ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9590565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190611900565b9290565b9180830292818404149015171561191357565b61034a6118c5565b9190820180921161191357565b369037565b9061034a61194361193d84610e7b565b93610e32565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00160208401611928565b90600160209161197c845190565b81101561198a575b02010190565b61199261088b565b611984565b60019080156119a4570390565b6119ac6118c5565b0390565b61155c61036e61036e9290565b61036e906119d56119d161036e9460ff1690565b9190565b901c90565b156119e157565b60405162461bcd60e51b815280611709600482016020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b9190600290611a5b611a56611a4783611a4286610de9565b6118f5565b611a5085610de9565b9061191b565b61192d565b916000916030611a73611a6d85610de9565b8661196e565b53611ac7611abe7f780000000000000000000000000000000000000000000000000000000000000092611a426001958695881a611ab8611ab288610de9565b8b61196e565b53610de9565b611a5083610de9565b915b611aea575b505061036e9293611ae46119d161036e93610de9565b146119da565b9094611af582610de9565b861115611b8157611b6e611b688392611b4b611b2e7f303132333435363738396162636465660000000000000000000000000000000090565b611b38600f610de9565b83166010811015611b74575b1a60f81b90565b861a611b578a8961196e565b53611b6260046119b0565b906119bd565b96611997565b91611ac9565b611b7c61088b565b611b44565b94611ace565b61036e61036e61036e9273ffffffffffffffffffffffffffffffffffffffff1690565b61036e60146119b0565b61036e61036e61036e9260ff1690565b611be1611bdc61036e92611bd6606090565b5061153b565b611b87565b6116c6611bec611baa565b611bb4565b15611bf857565b60405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201527f696e7461696e65720000000000000000000000000000000000000000000000006064820152608490fd5b61034a90611c9a611c95335b7f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab9561156c565b611bf1565b61034a90611ca781611544565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91613da0565b61034a90611c63565b61034a90611ce8611c9533611c6f565b611e94565b90611cfc61106e611064845190565b9060005b818110611d0d5750505090565b909192611d2061109c60019286516110ab565b929101611d00565b602080825261036e92910190611ced565b919060086117d3910291611d6c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841b90565b921b90565b9190611d8261036e6117f493610de9565b908354611d39565b61034a91600091611d71565b818110611da1575050565b80611daf6000600193611d8a565b01611d96565b9091828110611dc357505050565b61034a9290611dd9905b92600052602060002090565b9081019101611d96565b9061034a91680100000000000000008211611e04575b805490828155611db5565b611e0c6105c6565b611df9565b61036e9051610355565b6001611e4c611dcd611e2b855190565b9467ffffffffffffffff8611611e7d575b611e468686611de3565b60200190565b92049160005b838110611e5f5750505050565b6001906020611e7061036e86611e11565b9401938184015501611e52565b611e856105c6565b611e3c565b9061034a91611e1b565b61034a907f658ff1688002926d8f426cb10c052ec29003f50042df9652d8613484c1a58647611ec260405190565b80611ecd8482611d28565b0390a16003611e8a565b61034a90611cd8565b61034a90611ef0611c9533611c6f565b61034a907febf7325f48e05e5e38809c69f8b02a7c907ed31d8768e6c2d841b1296a9225fe611f1e60405190565b80611f298482611d28565b0390a16004611e8a565b61034a90611ee0565b61034a90611f4c611c9533611c6f565b611fa7565b90815260408101929161034a9160200152565b0152565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff906117d3565b90611fa061036e6117f492610de9565b8254611f68565b61034a90611fb56001611592565b817f4bb8a6184424e4bb853a4836042f5a726e4e710873989bfc6abdab19966f5b7091611fed611fe460405190565b92839283611f51565b0390a16001611f90565b61034a90611f3c565b61034a90612010611c9533611c6f565b612076565b61036e90610355565b61036e9054612015565b91602061034a929493610a8c60408201966000830190610388565b9073ffffffffffffffffffffffffffffffffffffffff906117d3565b9061206f61036e6117f492611544565b8254612043565b61034a90612084600261201e565b817fb2c853ac4d80d18d058c43d8018d077a036e542a79acae1647f5ad2a8c76f4e2916120bc6120b360405190565b92839283612028565b0390a1600261205f565b61034a90612000565b9050519061034a82610470565b9050519061034a826104db565b919061036e9060408482031261210d575b61210481856120cf565b936020016120dc565b612115600080fd5b6120fa565b90815260608101939261034a929091604091610a8c905b6020830190610388565b506040513d6000823e3d90fd5b9092604090949294612158600090565b956121996000966121a261217c612177612177610918600498896108bb565b611544565b9363ef99893a9261218c60405190565b9889978896879660e01b90565b8652850161211a565b03915afa806000809390926121df575b506121d957505060016121c157565b9150506000906119d16121d383610da4565b92610de9565b93509150565b909250612203915060403d811161220a575b6121fb81836105f6565b8101906120e9565b91386121b2565b503d6121f1565b61036e60a0610643565b612223612211565b906000825260208080808086016000815201600081520160005b8152016000905250565b61036e61221b565b60019060ff1660ff8114612261570190565b610e6f6118c5565b9160209181101561227957020190565b61067761088b565b3561036e81610785565b9061039190610355565b90919294936122a2612247565b506122ab612247565b9360005b826122b982611bb4565b10156123ef5760048460406122ec6109186122e66122e18e8a6122db8a611bb4565b91612269565b612281565b856108bb565b926122f961217785611544565b61219963ef99893a61230f898d61218c60405190565b03915afa600091829190816123cc575b5061233657505050612331905b61224f565b6122af565b600092612342846119b0565b60ff86161480156123b6575b612360575b505050506123319061224f565b6123319499506123ac929161238261238b9261237a612211565b96870161228b565b6020850161228b565b612398886040850161228b565b6123a5856060850161228b565b6080830152565b9590388080612353565b506123c561036e60808c015190565b831161234e565b9092506123e7915060403d811161220a576121fb81836105f6565b90913861231f565b5093955050505050565b90612402612247565b5061240b612247565b9160005b600461241c61036e825490565b61242583611bb4565b101561252b5782604061243b61091885856108bb565b9261244861217785611544565b61219963ef99893a61245e8c8b61218c60405190565b03915afa60009182919081612508575b5061248a5750505061248590600161232c5761224f565b61240f565b600092612496846119b0565b60ff86161480156124f2575b6124b4575b505050506124859061224f565b6124859497506124e892916123826124ce9261237a612211565b6124db866040850161228b565b6123a5886060850161228b565b93903880806124a7565b5061250161036e60808a015190565b83116124a2565b909250612523915060403d811161220a576121fb81836105f6565b90913861246e565b50505050905090565b61253c612211565b9060608252602080808080860160608152016060815201606061223d565b61036e612534565b1561256957565b60405162461bcd60e51b815260206004820152601c60248201527f59616b526f757465723a20496e76616c6964206d61782d7374657073000000006044820152606490fd5b90610e8861068c83610657565b9061034a6119436125cb846125ae565b93610657565b906020809161197c845190565b61036e6000610e7b565b9290949391956125f661255a565b50600061260281610de9565b84118061276c575b61261390612562565b61261d8786613ff1565b958861262883610de9565b82111561275c57612638916127d6565b600396612643885490565b9561265d612658612652885190565b8961191b565b6125bb565b9a61266785610de9565b8c898210156126a0579061269561269b92612690838f6109188261268a926108bb565b926125d1565b61228b565b60010190565b612667565b505091939597999092949698506126b686610de9565b6126c161036e8a5190565b8110156126fc57806126958b6126908f6126f1858f6126e66126f7996126eb926125d1565b611e11565b9461191b565b906125d1565b6126b6565b50909193959992949750612714965061036e986129c7565b9061272160208301515190565b61272d6119d183610de9565b14612739575b5061413a565b6127479082016103916125de565b612756604082016103916125de565b38612733565b505061276781610de9565b612638565b5061261361277a6005610de9565b8510905061260a565b9190820391821161191357565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81156127ca570490565b6127d2612790565b0490565b90919061282560009360606002917f000000000000000000000000000000000000000000000000000000000000000061281f612819670de0b6b3a7640000610de9565b94610de9565b9361288d565b6040810151519060009161283b6119d184610de9565b0361284557505050565b61036e93945061287661287a9392611a4292016126f1612866825192515190565b6128706001610de9565b90612783565b5190565b612887633b9aca00610de9565b906127c0565b91909261289861255a565b506000956128a587610de9565b861180612993575b6128b690612562565b6128c08585613ff1565b946003976128cc895490565b956128db612658612652875190565b976128e583610de9565b8881101561290c57806126958b6126908f9461268a61091882612907986108bb565b6128e5565b509193959890929496995061292084610de9565b61292b61036e895190565b81101561296057806126958c6126906129558461294f6126e68f9861295b996125d1565b9361191b565b8d6125d1565b612920565b509193969092955061298394985061036e9761297b87610de9565b9788956129c7565b9161272d61036e60208501515190565b506128b66129a16005610de9565b871090506128ad565b9061036e91602081830312156120cf576129c2600080fd5b6120cf565b929093959194956129d661255a565b506129e08761402d565b9182976129eb600090565b9586906000906129fa82610de9565b881196612a088c8c846123f9565b906080820191612a16835190565b612a226119d187610de9565b11612d50575b505050600199612a378b610de9565b871180612d16575b612a53575b50505050505050505050505090565b908291612a618c9594610de9565b945b612a6e575b50612a44565b612a7961036e885190565b851015612d11578c94612a926117b56126e6838b6125d1565b612a9b83610355565b14612d02578a8a8a8a612abb612ab46126e687846125d1565b87896123f9565b9960808b019a612ac98c5190565b612ad56119d18c610de9565b14612ced57612ae38d61402d565b94612c47575b8b6128768c8c612b419a9b9c9d9e9f94612b0f612b07612b2e975190565b928201611e11565b612b276060612b2060208501611e11565b9301611e11565b928b6140c3565b612b3b6126e689856125d1565b906129c7565b8d612b57612b516117b58461427b565b91610355565b1480612c27575b612b75575b506001015b9a5b9a939291908b612a63565b9a8b919e91608081018c612b87825190565b916080860192612b9b6119d161036e865190565b11612bc4575b505050612b689250612bbc9150805160409091015151015190565b9a9d90612b63565b84612c01612bf261287a6119d195612bec612c0698612870612be761036e995190565b915190565b906118f5565b95805160409091015151015190565b612783565b11612c14578b818c81612ba1565b9a509c612c219060010190565b9a612b6a565b508b612c416119d16118fc84805160409091015151015190565b11612b5e565b899b8a9b5061287682612c886020612c70612b419c9d9e9f61217761217791612b2e9901611e11565b6369cff80d90612c7f60405190565b93849260e01b90565b825260049082905afa908115612ce0575b600091612cb2575b509d509250509b9998979650612ae9565b612cd3915060203d8111612cd9575b612ccb81836105f6565b8101906129aa565b38612ca1565b503d612cc1565b612ce861213b565b612c99565b505050505050612c2191929394955060010190565b612c2191929394955060010190565b612a68565b50612d30612d2660208701515190565b6128876020610de9565b612d496119d161036e612d436002610de9565b8b612783565b1115612a3f565b9091929a5088612da0575b84839261287692612d6d612d97965190565b612d78888301611e11565b90612d916060612d8a60208601611e11565b9401611e11565b936140c3565b97388080612a28565b612d979291945080612dc16020612c70612177612177896128769701611e11565b825260049082905afa908115612e04575b600091612de6575b50959293509050612d5b565b612dfe915060203d8111612cd957612ccb81836105f6565b38612dda565b612e0c61213b565b612dd2565b90612e1e92913390612f91565b50565b3561036e81610470565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe13682900301821215612e8f575b01602081359167ffffffffffffffff8311612e82575b0191602082023603831361034257565b612e8a600080fd5b612e72565b612e97600080fd5b612e5c565b3561036e816104db565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612261570190565b61039190610de9565b9095949261034a94612f15610a8c92612f0b608096612f0160a088019c6000890152565b6020870190612ed4565b6040850190610388565b6060830190610388565b15612f2657565b60405162461bcd60e51b815260206004820152602560248201527f59616b526f757465723a20496e73756666696369656e74206f7574707574206160448201527f6d6f756e740000000000000000000000000000000000000000000000000000006064820152608490fd5b92939183916131079161303c90612fa785612e21565b90612fb26000610de9565b811180156134c9575b61347a575b506020612feb612177612177612fe6612fdc60408b018b612e2b565b6122db6000610de9565b612e9c565b612ffe612fe6612fdc60808a018a612e2b565b9061300860405190565b948592839182917f70a08231000000000000000000000000000000000000000000000000000000005b835260048301610395565b03915afa91821561346d575b60009261344b575b508192613085925061306b612fe6612fdc6040890189612e2b565b9061307f612fe6612fdc60808a018a612e2b565b91613573565b6130ed60206130a3612177612177612fe6612fdc60408a018a612e2b565b6130b6612fe6612fdc6080890189612e2b565b906130c060405190565b938492839182917f70a0823100000000000000000000000000000000000000000000000000000000613031565b03915afa908115613321575b600091613303575b50612783565b93613133612fe661311b6040850185612e2b565b6122db61286661312e6040890189612e2b565b905090565b9261313e6000610de9565b955b606084019061315561036e61312e8488612e2b565b8810156133c25790879161317261036e61286661312e858a612e2b565b8310156133ba578561319a612fe661318d6080840184612e2b565b6122db6126526001610de9565b915b6131c8612177612177612fe66131b56040870187612e2b565b6122db6131c26001610de9565b8c61191b565b9360206131d460405190565b9586907f70a0823100000000000000000000000000000000000000000000000000000000825281806132098960048301610395565b03915afa9485156133ad575b60009561336e575b50926132ef612177612177612fe6896122db6132a3896000806132fd9f9b6132f79f9e8f6130ed9f60209f8f93613270612177612177612fe68561326a6132d4968d996132c99b50612e2b565b90612269565b94896132b0612fe663eab90da6956122db6132a3613298612fe68461326a60408a018a612e2b565b956040810190612e2b565b919092611a506001610de9565b90873b15613361575b6040519a8b998a98899760e01b90565b875260048701612edd565b03925af18015613354575b61332e575b506040810190612e2b565b6040516130c0565b96612ea6565b95613140565b61331b915060203d8111612cd957612ccb81836105f6565b38613101565b61332961213b565b6130f9565b6133479060005b61333f81836105f6565b810190610337565b386132e4565b503d613335565b61335c61213b565b6132df565b613369600080fd5b6132b9565b839550868593949592819260203d81116133a6575b61338d81836105f6565b8101613398916129aa565b97509250509392919361321d565b503d613383565b6133b561213b565b613215565b85859161319c565b9594936133fd9297506134039350612fe69150612fdc906133f36133eb61036e60208401612e21565b891015612f1f565b6040810190612e2b565b92612e21565b91836134386134327f9fc8352e52998db4087d5e6e1c1aafa38788e749e5d7a24f5cb230f73795440293611544565b93611544565b93613445611fe460405190565b0390a390565b61308592506134679060203d8111612cd957612ccb81836105f6565b91613050565b61347561213b565b613048565b61348d915061348888612e21565b613533565b6134c3816134a4612fe6612fdc60408a018a612e2b565b90856134bd6134b3600261201e565b92612c018d612e21565b92613573565b38612fc0565b506134d46001611592565b6134e16119d16000610de9565b11612fbb565b156134ee57565b60405162461bcd60e51b815260206004820152601b60248201527f59616b526f757465723a20496e73756666696369656e742066656500000000006044820152606490fd5b9061356e61036e92613543600090565b5061355c61355461036e6001611592565b8410156134e7565b612bec613567611259565b9384612783565b6127c0565b9291906135826117b530611544565b61358b82610355565b146135a15761359c61034a94611544565b613cf8565b506135ae61034a93611544565b613c90565b156135ba57565b60405162461bcd60e51b815260206004820152602860248201527f59616b526f757465723a2050617468206e6565647320746f20626567696e207760448201527f69746820574554480000000000000000000000000000000000000000000000006064820152608490fd5b90612e1e929161369361368e612fe66136876136556136476040870187612e2b565b93906000946122db86610de9565b613681612b517f0000000000000000000000000000000000000000000000000000000000000000610355565b146135b3565b8301612e21565b6136a2565b61369c30611544565b90612f91565b60006136ee6136d36121777f0000000000000000000000000000000000000000000000000000000000000000611544565b63d0e30db0813b15613725575b604051948593849260e01b90565b825281600481015b03925af18015613718575b6137085750565b61034a90600061333f81836105f6565b61372061213b565b613701565b61372d600080fd5b6136e0565b1561373957565b60405162461bcd60e51b815260206004820152602660248201527f59616b526f757465723a2050617468206e6565647320746f20656e642077697460448201527f68205745544800000000000000000000000000000000000000000000000000006064820152608490fd5b6138189061034a93926138086137d6612fe66040850161312e6122db6128666137cd848a612e2b565b9390948a612e2b565b613802612b517f0000000000000000000000000000000000000000000000000000000000000000610355565b14613732565b3361381230611544565b92612f91565b6138218161382e565b613829610dad565b61389c565b60006136f6916138606121777f0000000000000000000000000000000000000000000000000000000000000000611544565b61388183632e1a7d4d833b1561388f575b6040519687958694859360e01b90565b835260048301526024820190565b613897600080fd5b613871565b916138a630611544565b6138b2612b5183610355565b036138bc57505050565b6138c76117b5610dad565b6138d084610355565b0361390a57600080935080926138e96121778394611544565b828215613901575bf1156138f957565b61034a61213b565b506108fc6138f1565b6135ae61034a93611544565b949290979695939160e08601986000870161393091610388565b6020860161393d91610388565b6040850152606084015260ff16608083015260a082015260c00152565b929561034a96612fe693966139cc6139d787959861397b6040880188612e2b565b92909661399761217761217760009c8d9b8c986122db8a610de9565b9563d505accf9333986139b4876139ad30611544565b9d01612e21565b893b15613a18575b6040519c8d9b8c9a8b9960e01b90565b895260048901613916565b03925af18015613a0b575b6139ee575b5050612e11565b81613a0492903d1061334d5761333f81836105f6565b38806139e7565b613a1361213b565b6139e2565b613a20600080fd5b6139bc565b929561034a96612fe693966139cc613a4687959861397b6040880188612e2b565b03925af18015613a7a575b613a5d575b50506137a4565b81613a7392903d1061334d5761333f81836105f6565b3880613a56565b613a8261213b565b613a51565b61034a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab956115db565b61034a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95611728565b61034a903361058b565b61034a903390613afd613af6610df6565b91826115db565b6117a4565b61034a9190613b13611c9533611c6f565b613b64565b15613b1f57565b60405162461bcd60e51b815260206004820152601260248201527f4e6f7468696e6720746f207265636f76657200000000000000000000000000006044820152606490fd5b613b79613b716000610de9565b835b11613b18565b613b8d82613b8683611544565b3390613c90565b613bc4613bba7f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa2892611544565b926104c160405190565b0390a2565b9061034a91613b02565b61034a90613be3611c9533611c6f565b613b8d6000613bfa613bf482610de9565b84613b73565b8080808086613c0b61217733611544565b828215613c25575bf1610da457613c2061213b565b610da4565b506108fc613c13565b61034a90613bd3565b613c50613c4a61036e9263ffffffff1690565b60e01b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b91602061034a929493611f6460408201966000830190610388565b613cd3600492613cc461034a95613caa63a9059cbb613c37565b92613cb460405190565b9687946020860190815201613c75565b602082018103825203836105f6565b613f90565b604090611f6461034a949695939661213160608401986000850190610388565b90613cd390613cc461034a95600495613d146323b872dd613c37565b93613d1e60405190565b9788956020870190815201613cd8565b15613d3557565b60405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608490fd5b613cd3600492613cc461034a95613dcd600084613dbc82610de9565b8414918215613dda575b5050613d2e565b613caa63095ea7b3613c37565b9091506020613de889611544565b63dd62ed3e90613e14613dfa30611544565b92613e1f613e0760405190565b9788958694859460e01b90565b845260048401612028565b03915afa918215613e70575b600092613e48575b506119d1613e4091610de9565b148438613dc6565b613e40919250613e686119d19160203d8111612cd957612ccb81836105f6565b929150613e33565b613e7861213b565b613e2b565b3d15613e9757613e8c3d610e7b565b903d6000602084013e565b606090565b15613ea357565b60405162461bcd60e51b815280611709600482016020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b801515610403565b9050519061034a82613eec565b9061036e9160208183031215613ef457613f19600080fd5b613ef4565b15613f2557565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608490fd5b600091613f9d8392611544565b9082602082019151925af1613fb9613fb3613e7d565b91613e9c565b8051613fc86119d16000610de9565b11613fd05750565b613fec816020613fe161034a945190565b818301019101613f01565b613f1e565b9190604061401261400061255a565b9261400b8496614017565b8452614017565b910152565b90602091614027611a5684610de9565b92830152565b61403561255a565b5061036e6000820151916123a5602082015191614082604082015161407b6140636080606086015195015190565b9561407461406f612211565b998a52565b6020890152565b6040870152565b6060850152565b6116529061036e93926115f9565b6140b7929161034a916140a960405190565b948592602084019283614089565b908103825203836105f6565b90926103919360809361034a97966140ea60408601916140e4835191614017565b90614097565b90526140ff60208501916140e4835191614017565b905261411460008401916140e4835191614017565b905261412960608301916140e4835191614017565b90520191614135835190565b61191b565b61414261255a565b5061036e6141536000830151614219565b916123a56141646020830151614190565b916140826141756040830151614190565b61407b614063608061418a6060870151614190565b95015190565b908151916141a661265860209461288786610de9565b92836141b26000610de9565b6141c961036e6141c0865190565b61288786610de9565b8110156142125761420d906142086141fe6141f86141ef6141e988610de9565b856118f5565b611a5088610de9565b87015190565b612690838a6125d1565b612ea6565b6141b2565b5093505050565b9081519161422f61265860209461288786610de9565b928361423b6000610de9565b61424961036e6141c0865190565b81101561421257614276906142086142696141f86141ef6141e988610de9565b614273838a6125d1565b52565b61423b565b604061036e91614289600090565b500151805101519056fea26469706673582212209bab7ef2e02c88142d1a19cfb4bd54703a6e2d7623fefdd4d93a123ad69be2eb64736f6c63430008110033339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab950000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001bb7b44cc398aaa2b76ac6253f0f5634279db9d00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b5570000000000000000000000000000000000000000000000000000000000000003000000000000000000000000f05902d8eb53a354c9ddc67175df3d9bee1f95810000000000000000000000009cc2b9f9a6194c5cc827c88571e42ceaa76fdf4700000000000000000000000036049d5b4aaef6c39cd4a5bd1a2e1224f07621a20000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cf800f4948d16f23333508191b1b1591daf70438000000000000000000000000a2235d059f80e176d931ef76b6c51953eb3fbef400000000000000000000000048b62137edfa95a428d35c09e44256a739f6b557
Deployed Bytecode
0x6080604052600436101561001e575b361561001c5761001c600080fd5b005b60003560e01c8062b99e361461032957806301ffc9a714610320578063248a9ca3146103175780632f2ff15d1461030e57806331ac99201461030557806336568abe146102fc5780633a9a4081146102f35780633cf57ac7146102ea578063414cff85146102e157806352a52ab0146102d85780636b453c1f146102cf57806376c7a3c7146102c657806376ebe69c146102bd5780637c7a561b146102b4578063809356aa146102ab57806383637d14146102a25780638980f11f146102995780638bb9c5bf1461029057806391d148541461028757806392f5d88a1461027e578063952e901214610275578063a0cf0aea1461026c578063a217fddf14610263578063a3f4df7e1461025a578063aede369314610251578063b381cf4014610248578063b9a89ca31461023f578063befe980314610236578063c3accd481461022d578063c8a3a5c614610224578063ce6e28f21461021b578063d547741f14610212578063d73792a914610209578063d8baf7cf14610200578063dd8544b3146101f7578063dede7f15146101ee578063f2fde38b146101e5578063f6ee13a6146101dc5763f87422540361000e576101d7611424565b61000e565b506101d76113f3565b506101d7611344565b506101d7611319565b506101d76112bd565b506101d7611296565b506101d761126c565b506101d7611231565b506101d7611209565b506101d76111e2565b506101d76111bb565b506101d76111a6565b506101d761116c565b506101d7610f93565b506101d7610f6c565b506101d7610f36565b506101d7610e08565b506101d7610dbf565b506101d7610d6d565b506101d7610d27565b506101d7610bda565b506101d7610bb3565b506101d7610b8b565b506101d7610b32565b506101d7610a93565b506101d7610a06565b506101d76109db565b506101d76109b1565b506101d7610968565b506101d7610921565b506101d761085d565b506101d761082f565b506101d7610748565b506101d7610576565b506101d761054f565b506101d7610522565b506101d76104a0565b506101d7610434565b506101d76103a5565b600080fd5b600091031261034257565b61034a600080fd5b565b61036e916008021c5b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b9061036e915461034c565b61036e60006002610371565b61039190610355565b9052565b60208101929161034a9190610388565b50346103d2575b6103b7366004610337565b6103ce6103c261037c565b60405191829182610395565b0390f35b6103da600080fd5b6103ac565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b0361033257565b9050359061034a826103df565b9061036e916020818303121561040a5761042f600080fd5b61040a565b5034610463575b6103ce61045161044c366004610417565b61146c565b60405191829182901515815260200190565b61046b600080fd5b61043b565b80610403565b9050359061034a82610470565b9061036e91602081830312156104765761049b600080fd5b610476565b50346104ce575b6103ce6104bd6104b8366004610483565b61159c565b6040515b9182918290815260200190565b6104d6600080fd5b6104a7565b61040381610355565b9050359061034a826104db565b919061036e90604084820312610515575b61050c8185610476565b936020016104e4565b61051d600080fd5b610502565b5034610542575b61053d6105373660046104f1565b906115db565b604051005b61054a600080fd5b610529565b5034610569575b61053d610564366004610483565b611ff7565b610571600080fd5b610556565b5034610591575b61053d61058b3660046104f1565b906117a4565b610599600080fd5b61057d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810190811067ffffffffffffffff82111761063657604052565b61063e6105c6565b604052565b9061034a61065060405190565b92836105f6565b6020809167ffffffffffffffff811161066f57020190565b6106776105c6565b020190565b9092919261069161068c82610657565b610643565b93818552602080860192028301928184116106cf575b915b8383106106b65750505050565b602080916106c484866104e4565b8152019201916106a9565b6106d7600080fd5b6106a7565b9061036e9181601f820112156106f8575b60208135910161067c565b610700600080fd5b6106ed565b9061036e9160208183031261073b575b80359067ffffffffffffffff821161072e575b016106dc565b610736600080fd5b610728565b610743600080fd5b610715565b5034610762575b61053d61075d366004610705565b611f33565b61076a600080fd5b61074f565b908160a091031261077d5790565b61036e600080fd5b60ff8116610403565b9050359061034a82610785565b60e081830312610822575b6107c382823567ffffffffffffffff8111610815575b830161076f565b926107d18360208401610476565b926107df81604085016104e4565b926107ed8260608301610476565b9261036e6107fe846080850161078e565b9361080c8160a08601610476565b9360c001610476565b61081d600080fd5b6107bc565b61082a600080fd5b6107a6565b5034610850575b61053d61084436600461079b565b95949094939193613a25565b610858600080fd5b610836565b503461087e575b61053d61087236600461079b565b9594909493919361395a565b610886600080fd5b610864565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6108db6001916108c9815490565b8410156108e457600052602060002090565b91020190600090565b6108ec61088b565b600052602060002090565b60036000610903825490565b83101561091e575061036e91610918916108bb565b90610371565b80fd5b503461093e575b6103ce6103c2610939366004610483565b6108f7565b610946600080fd5b610928565b9061036e91602081830312156104e457610963600080fd5b6104e4565b5034610982575b61053d61097d36600461094b565b613a87565b61098a600080fd5b61096f565b61036e916008021c81565b9061036e915461098f565b61036e6000600161099a565b50346109ce575b6109c3366004610337565b6103ce6104bd6109a5565b6109d6600080fd5b6109b8565b50346109f9575b6109ed366004610337565b6103ce6104bd60035490565b610a01600080fd5b6109e2565b5034610a24575b610a18366004610337565b6103ce6104bd60045490565b610a2c600080fd5b610a0d565b608081830312610a6e575b610a468282610476565b9261036e610a5784602085016104e4565b93610a6581604086016104e4565b9360600161078e565b610a76600080fd5b610a3c565b90815260408101929161034a916020905b0190610388565b5034610ac7575b610ab1610aa8366004610a31565b92919091612148565b906103ce610abe60405190565b92839283610a7b565b610acf600080fd5b610a9a565b9091606082840312610b25575b61036e610b0184843567ffffffffffffffff8111610b18575b850161076f565b93610b0f8160208601610476565b936040016104e4565b610b20600080fd5b610afa565b610b2d600080fd5b610ae1565b5034610b4d575b61053d610b47366004610ad4565b916137a4565b610b55600080fd5b610b39565b919061036e90604084820312610b7e575b610b7581856104e4565b93602001610476565b610b86600080fd5b610b6b565b5034610ba6575b61053d610ba0366004610b5a565b90613bc9565b610bae600080fd5b610b92565b5034610bcd575b61053d610bc8366004610483565b613adb565b610bd5600080fd5b610bba565b5034610bf8575b6103ce610451610bf23660046104f1565b9061156c565b610c00600080fd5b610be1565b909182601f83011215610c44575b602082359267ffffffffffffffff8411610c37575b01926020830284011161034257565b610c3f600080fd5b610c28565b610c4c600080fd5b610c13565b608081830312610cb3575b610c668282610476565b92610ca2610c7784602085016104e4565b93610c8581604086016104e4565b9360608101359067ffffffffffffffff8211610ca6575b01610c05565b9091565b610cae600080fd5b610c9c565b610cbb600080fd5b610c5c565b9060808061034a93610cda60008201516000860190610388565b610cec60208201516020860190610388565b610cfe60408201516040860190610388565b610d1060608201516060860190610388565b0151910152565b60a08101929161034a9190610cc0565b5034610d54575b6103ce610d48610d3f366004610c51565b93929092612295565b60405191829182610d17565b610d5c600080fd5b610d2e565b60046000610903825490565b5034610d8a575b6103ce6103c2610d85366004610483565b610d61565b610d92600080fd5b610d74565b61035561036e61036e9290565b61036e90610d97565b61036e6000610da4565b61036e610dad565b5034610ddc575b610dd1366004610337565b6103ce6103c2610db7565b610de4600080fd5b610dc6565b61036e61036e61036e9290565b61036e6000610de9565b61036e610df6565b5034610e25575b610e1a366004610337565b6103ce6104bd610e00565b610e2d600080fd5b610e0f565b610e6f60209167ffffffffffffffff8111610e7357601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690565b0190565b61059e6105c6565b90610e8861068c83610e32565b918252565b610e976010610e7b565b7f43616d656c6f7459616b526f7574657200000000000000000000000000000000602082015290565b61036e610e8d565b61036e610ec0565b61036e610ec8565b60005b838110610eeb5750506000910152565b8181015183820152602001610edb565b610f1c61059e602093610e6f93610f10815190565b80835293849260200190565b95869101610ed8565b602080825261036e92910190610efb565b5034610f5f575b610f48366004610337565b6103ce610f53610ed0565b60405191829182610f25565b610f67600080fd5b610f3d565b5034610f86575b61053d610f81366004610483565b613c2e565b610f8e600080fd5b610f73565b5034610fce575b610fa5366004610337565b6103ce7f00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b5576103c2565b610fd6600080fd5b610f9a565b919060a083820312611048575b610ff28184610476565b9261100082602083016104e4565b9261036e61101184604085016104e4565b9361103281606086013567ffffffffffffffff811161103b575b86016106dc565b93608001610476565b611043600080fd5b61102b565b611050600080fd5b610fe8565b9061107561106e611064845190565b8084529260200190565b9260200190565b9060005b8181106110865750505090565b9091926110a361109c6001928651815260200190565b9460200190565b929101611079565b90610e6f81602093610388565b906110c761106e611064845190565b9060005b8181106110d85750505090565b9091926110eb61109c60019286516110ab565b9291016110cb565b9061036e9060808061115361114161112f61111d60a0870160008a015188820360008a0152611055565b602089015187820360208901526110b8565b604088015186820360408801526110b8565b606087015185820360608701526110b8565b940151910152565b602080825261036e929101906110f3565b5034611199575b6103ce61118d611184366004610fdb565b9392909261288d565b6040519182918261115b565b6111a1600080fd5b611173565b5061053d6111b5366004610ad4565b91613625565b50346111d5575b61053d6111d036600461094b565b6120c6565b6111dd600080fd5b6111c2565b50346111fc575b61053d6111f7366004610705565b611ed7565b611204600080fd5b6111e9565b5034611224575b61053d61121e366004610ad4565b91612e11565b61122c600080fd5b611210565b503461124c575b61053d6112463660046104f1565b90611728565b611254600080fd5b611238565b61036e612710610de9565b61036e611259565b5034611289575b61127e366004610337565b6103ce6104bd611264565b611291600080fd5b611273565b50346112b0575b61053d6112ab36600461094b565b613ab1565b6112b8600080fd5b61129d565b50346112d7575b61053d6112d236600461094b565b611ccf565b6112df600080fd5b6112c4565b909160608284031261130c575b61036e6112fe8484610476565b93610b0f81602086016104e4565b611314600080fd5b6112f1565b5034611337575b6103ce610d486113313660046112e4565b916123f9565b61133f600080fd5b611320565b503461135e575b61053d61135936600461094b565b613ae5565b611366600080fd5b61134b565b909160c0828403126113e6575b6113828383610476565b9261139081602085016104e4565b9261139e82604083016104e4565b9261036e6113c284606085013567ffffffffffffffff81116113d9575b85016106dc565b936113d08160808601610476565b9360a001610476565b6113e1600080fd5b6113bb565b6113ee600080fd5b611378565b5034611417575b6103ce61118d61140b36600461136b565b949390939291926125e8565b61141f600080fd5b6113fa565b503461145f575b611436366004610337565b6103ce7f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab956104bd565b611467600080fd5b61142b565b7f7965db0b000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216149081156114bc575090565b61036e91507fffffffff00000000000000000000000000000000000000000000000000000000167f01ffc9a7000000000000000000000000000000000000000000000000000000001490565b905b600052602052604060002090565b61035561036e61036e9273ffffffffffffffffffffffffffffffffffffffff1690565b61036e90611518565b61036e9061153b565b9061150a90611544565b61036e905b60ff1690565b61036e9054611557565b61036e916115869161158060009182611508565b0161154d565b611562565b61036e9081565b61036e905461158b565b60016115b561036e926115ad600090565b506000611508565b01611592565b9061034a916115d16115cc8261159c565b6115e5565b9061034a916117f8565b9061034a916115bb565b61034a903390611681565b61036e90610de9565b610e6f6116119260209261160b815190565b94859290565b93849101610ed8565b61165861036e9392611652611652937f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260170190565b906115f9565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000815260110190565b9061169361168f828461156c565b1590565b61169b575050565b6117099161036e6116b76116b16116f194611bc4565b926115f0565b6116cc6020916116c683610de9565b90611a2a565b926116e56116d960405190565b9485938401928361161a565b908103825203826105f6565b60405191829162461bcd60e51b835260048301610f25565b0390fd5b9061034a9161171e6115cc8261159c565b9061034a9161186e565b9061034a9161170d565b1561173957565b60405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608490fd5b61034a91906117c96117ba33610355565b610355565b6117c384610355565b14611732565b61186e565b9060ff905b9181191691161790565b906117ed61036e6117f492151590565b82546117ce565b9055565b9061180661168f828461156c565b61180e575050565b61182860016118238360006115808782611508565b6117dd565b339061185e6118586118587f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9590565b92611544565b9261186860405190565b600090a4565b90611879818361156c565b611881575050565b611895600061182383826115808782611508565b339061185e6118586118587ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9590565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190611900565b9290565b9180830292818404149015171561191357565b61034a6118c5565b9190820180921161191357565b369037565b9061034a61194361193d84610e7b565b93610e32565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00160208401611928565b90600160209161197c845190565b81101561198a575b02010190565b61199261088b565b611984565b60019080156119a4570390565b6119ac6118c5565b0390565b61155c61036e61036e9290565b61036e906119d56119d161036e9460ff1690565b9190565b901c90565b156119e157565b60405162461bcd60e51b815280611709600482016020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b9190600290611a5b611a56611a4783611a4286610de9565b6118f5565b611a5085610de9565b9061191b565b61192d565b916000916030611a73611a6d85610de9565b8661196e565b53611ac7611abe7f780000000000000000000000000000000000000000000000000000000000000092611a426001958695881a611ab8611ab288610de9565b8b61196e565b53610de9565b611a5083610de9565b915b611aea575b505061036e9293611ae46119d161036e93610de9565b146119da565b9094611af582610de9565b861115611b8157611b6e611b688392611b4b611b2e7f303132333435363738396162636465660000000000000000000000000000000090565b611b38600f610de9565b83166010811015611b74575b1a60f81b90565b861a611b578a8961196e565b53611b6260046119b0565b906119bd565b96611997565b91611ac9565b611b7c61088b565b611b44565b94611ace565b61036e61036e61036e9273ffffffffffffffffffffffffffffffffffffffff1690565b61036e60146119b0565b61036e61036e61036e9260ff1690565b611be1611bdc61036e92611bd6606090565b5061153b565b611b87565b6116c6611bec611baa565b611bb4565b15611bf857565b60405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201527f696e7461696e65720000000000000000000000000000000000000000000000006064820152608490fd5b61034a90611c9a611c95335b7f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab9561156c565b611bf1565b61034a90611ca781611544565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91613da0565b61034a90611c63565b61034a90611ce8611c9533611c6f565b611e94565b90611cfc61106e611064845190565b9060005b818110611d0d5750505090565b909192611d2061109c60019286516110ab565b929101611d00565b602080825261036e92910190611ced565b919060086117d3910291611d6c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841b90565b921b90565b9190611d8261036e6117f493610de9565b908354611d39565b61034a91600091611d71565b818110611da1575050565b80611daf6000600193611d8a565b01611d96565b9091828110611dc357505050565b61034a9290611dd9905b92600052602060002090565b9081019101611d96565b9061034a91680100000000000000008211611e04575b805490828155611db5565b611e0c6105c6565b611df9565b61036e9051610355565b6001611e4c611dcd611e2b855190565b9467ffffffffffffffff8611611e7d575b611e468686611de3565b60200190565b92049160005b838110611e5f5750505050565b6001906020611e7061036e86611e11565b9401938184015501611e52565b611e856105c6565b611e3c565b9061034a91611e1b565b61034a907f658ff1688002926d8f426cb10c052ec29003f50042df9652d8613484c1a58647611ec260405190565b80611ecd8482611d28565b0390a16003611e8a565b61034a90611cd8565b61034a90611ef0611c9533611c6f565b61034a907febf7325f48e05e5e38809c69f8b02a7c907ed31d8768e6c2d841b1296a9225fe611f1e60405190565b80611f298482611d28565b0390a16004611e8a565b61034a90611ee0565b61034a90611f4c611c9533611c6f565b611fa7565b90815260408101929161034a9160200152565b0152565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff906117d3565b90611fa061036e6117f492610de9565b8254611f68565b61034a90611fb56001611592565b817f4bb8a6184424e4bb853a4836042f5a726e4e710873989bfc6abdab19966f5b7091611fed611fe460405190565b92839283611f51565b0390a16001611f90565b61034a90611f3c565b61034a90612010611c9533611c6f565b612076565b61036e90610355565b61036e9054612015565b91602061034a929493610a8c60408201966000830190610388565b9073ffffffffffffffffffffffffffffffffffffffff906117d3565b9061206f61036e6117f492611544565b8254612043565b61034a90612084600261201e565b817fb2c853ac4d80d18d058c43d8018d077a036e542a79acae1647f5ad2a8c76f4e2916120bc6120b360405190565b92839283612028565b0390a1600261205f565b61034a90612000565b9050519061034a82610470565b9050519061034a826104db565b919061036e9060408482031261210d575b61210481856120cf565b936020016120dc565b612115600080fd5b6120fa565b90815260608101939261034a929091604091610a8c905b6020830190610388565b506040513d6000823e3d90fd5b9092604090949294612158600090565b956121996000966121a261217c612177612177610918600498896108bb565b611544565b9363ef99893a9261218c60405190565b9889978896879660e01b90565b8652850161211a565b03915afa806000809390926121df575b506121d957505060016121c157565b9150506000906119d16121d383610da4565b92610de9565b93509150565b909250612203915060403d811161220a575b6121fb81836105f6565b8101906120e9565b91386121b2565b503d6121f1565b61036e60a0610643565b612223612211565b906000825260208080808086016000815201600081520160005b8152016000905250565b61036e61221b565b60019060ff1660ff8114612261570190565b610e6f6118c5565b9160209181101561227957020190565b61067761088b565b3561036e81610785565b9061039190610355565b90919294936122a2612247565b506122ab612247565b9360005b826122b982611bb4565b10156123ef5760048460406122ec6109186122e66122e18e8a6122db8a611bb4565b91612269565b612281565b856108bb565b926122f961217785611544565b61219963ef99893a61230f898d61218c60405190565b03915afa600091829190816123cc575b5061233657505050612331905b61224f565b6122af565b600092612342846119b0565b60ff86161480156123b6575b612360575b505050506123319061224f565b6123319499506123ac929161238261238b9261237a612211565b96870161228b565b6020850161228b565b612398886040850161228b565b6123a5856060850161228b565b6080830152565b9590388080612353565b506123c561036e60808c015190565b831161234e565b9092506123e7915060403d811161220a576121fb81836105f6565b90913861231f565b5093955050505050565b90612402612247565b5061240b612247565b9160005b600461241c61036e825490565b61242583611bb4565b101561252b5782604061243b61091885856108bb565b9261244861217785611544565b61219963ef99893a61245e8c8b61218c60405190565b03915afa60009182919081612508575b5061248a5750505061248590600161232c5761224f565b61240f565b600092612496846119b0565b60ff86161480156124f2575b6124b4575b505050506124859061224f565b6124859497506124e892916123826124ce9261237a612211565b6124db866040850161228b565b6123a5886060850161228b565b93903880806124a7565b5061250161036e60808a015190565b83116124a2565b909250612523915060403d811161220a576121fb81836105f6565b90913861246e565b50505050905090565b61253c612211565b9060608252602080808080860160608152016060815201606061223d565b61036e612534565b1561256957565b60405162461bcd60e51b815260206004820152601c60248201527f59616b526f757465723a20496e76616c6964206d61782d7374657073000000006044820152606490fd5b90610e8861068c83610657565b9061034a6119436125cb846125ae565b93610657565b906020809161197c845190565b61036e6000610e7b565b9290949391956125f661255a565b50600061260281610de9565b84118061276c575b61261390612562565b61261d8786613ff1565b958861262883610de9565b82111561275c57612638916127d6565b600396612643885490565b9561265d612658612652885190565b8961191b565b6125bb565b9a61266785610de9565b8c898210156126a0579061269561269b92612690838f6109188261268a926108bb565b926125d1565b61228b565b60010190565b612667565b505091939597999092949698506126b686610de9565b6126c161036e8a5190565b8110156126fc57806126958b6126908f6126f1858f6126e66126f7996126eb926125d1565b611e11565b9461191b565b906125d1565b6126b6565b50909193959992949750612714965061036e986129c7565b9061272160208301515190565b61272d6119d183610de9565b14612739575b5061413a565b6127479082016103916125de565b612756604082016103916125de565b38612733565b505061276781610de9565b612638565b5061261361277a6005610de9565b8510905061260a565b9190820391821161191357565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b81156127ca570490565b6127d2612790565b0490565b90919061282560009360606002917f00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b55761281f612819670de0b6b3a7640000610de9565b94610de9565b9361288d565b6040810151519060009161283b6119d184610de9565b0361284557505050565b61036e93945061287661287a9392611a4292016126f1612866825192515190565b6128706001610de9565b90612783565b5190565b612887633b9aca00610de9565b906127c0565b91909261289861255a565b506000956128a587610de9565b861180612993575b6128b690612562565b6128c08585613ff1565b946003976128cc895490565b956128db612658612652875190565b976128e583610de9565b8881101561290c57806126958b6126908f9461268a61091882612907986108bb565b6128e5565b509193959890929496995061292084610de9565b61292b61036e895190565b81101561296057806126958c6126906129558461294f6126e68f9861295b996125d1565b9361191b565b8d6125d1565b612920565b509193969092955061298394985061036e9761297b87610de9565b9788956129c7565b9161272d61036e60208501515190565b506128b66129a16005610de9565b871090506128ad565b9061036e91602081830312156120cf576129c2600080fd5b6120cf565b929093959194956129d661255a565b506129e08761402d565b9182976129eb600090565b9586906000906129fa82610de9565b881196612a088c8c846123f9565b906080820191612a16835190565b612a226119d187610de9565b11612d50575b505050600199612a378b610de9565b871180612d16575b612a53575b50505050505050505050505090565b908291612a618c9594610de9565b945b612a6e575b50612a44565b612a7961036e885190565b851015612d11578c94612a926117b56126e6838b6125d1565b612a9b83610355565b14612d02578a8a8a8a612abb612ab46126e687846125d1565b87896123f9565b9960808b019a612ac98c5190565b612ad56119d18c610de9565b14612ced57612ae38d61402d565b94612c47575b8b6128768c8c612b419a9b9c9d9e9f94612b0f612b07612b2e975190565b928201611e11565b612b276060612b2060208501611e11565b9301611e11565b928b6140c3565b612b3b6126e689856125d1565b906129c7565b8d612b57612b516117b58461427b565b91610355565b1480612c27575b612b75575b506001015b9a5b9a939291908b612a63565b9a8b919e91608081018c612b87825190565b916080860192612b9b6119d161036e865190565b11612bc4575b505050612b689250612bbc9150805160409091015151015190565b9a9d90612b63565b84612c01612bf261287a6119d195612bec612c0698612870612be761036e995190565b915190565b906118f5565b95805160409091015151015190565b612783565b11612c14578b818c81612ba1565b9a509c612c219060010190565b9a612b6a565b508b612c416119d16118fc84805160409091015151015190565b11612b5e565b899b8a9b5061287682612c886020612c70612b419c9d9e9f61217761217791612b2e9901611e11565b6369cff80d90612c7f60405190565b93849260e01b90565b825260049082905afa908115612ce0575b600091612cb2575b509d509250509b9998979650612ae9565b612cd3915060203d8111612cd9575b612ccb81836105f6565b8101906129aa565b38612ca1565b503d612cc1565b612ce861213b565b612c99565b505050505050612c2191929394955060010190565b612c2191929394955060010190565b612a68565b50612d30612d2660208701515190565b6128876020610de9565b612d496119d161036e612d436002610de9565b8b612783565b1115612a3f565b9091929a5088612da0575b84839261287692612d6d612d97965190565b612d78888301611e11565b90612d916060612d8a60208601611e11565b9401611e11565b936140c3565b97388080612a28565b612d979291945080612dc16020612c70612177612177896128769701611e11565b825260049082905afa908115612e04575b600091612de6575b50959293509050612d5b565b612dfe915060203d8111612cd957612ccb81836105f6565b38612dda565b612e0c61213b565b612dd2565b90612e1e92913390612f91565b50565b3561036e81610470565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe13682900301821215612e8f575b01602081359167ffffffffffffffff8311612e82575b0191602082023603831361034257565b612e8a600080fd5b612e72565b612e97600080fd5b612e5c565b3561036e816104db565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612261570190565b61039190610de9565b9095949261034a94612f15610a8c92612f0b608096612f0160a088019c6000890152565b6020870190612ed4565b6040850190610388565b6060830190610388565b15612f2657565b60405162461bcd60e51b815260206004820152602560248201527f59616b526f757465723a20496e73756666696369656e74206f7574707574206160448201527f6d6f756e740000000000000000000000000000000000000000000000000000006064820152608490fd5b92939183916131079161303c90612fa785612e21565b90612fb26000610de9565b811180156134c9575b61347a575b506020612feb612177612177612fe6612fdc60408b018b612e2b565b6122db6000610de9565b612e9c565b612ffe612fe6612fdc60808a018a612e2b565b9061300860405190565b948592839182917f70a08231000000000000000000000000000000000000000000000000000000005b835260048301610395565b03915afa91821561346d575b60009261344b575b508192613085925061306b612fe6612fdc6040890189612e2b565b9061307f612fe6612fdc60808a018a612e2b565b91613573565b6130ed60206130a3612177612177612fe6612fdc60408a018a612e2b565b6130b6612fe6612fdc6080890189612e2b565b906130c060405190565b938492839182917f70a0823100000000000000000000000000000000000000000000000000000000613031565b03915afa908115613321575b600091613303575b50612783565b93613133612fe661311b6040850185612e2b565b6122db61286661312e6040890189612e2b565b905090565b9261313e6000610de9565b955b606084019061315561036e61312e8488612e2b565b8810156133c25790879161317261036e61286661312e858a612e2b565b8310156133ba578561319a612fe661318d6080840184612e2b565b6122db6126526001610de9565b915b6131c8612177612177612fe66131b56040870187612e2b565b6122db6131c26001610de9565b8c61191b565b9360206131d460405190565b9586907f70a0823100000000000000000000000000000000000000000000000000000000825281806132098960048301610395565b03915afa9485156133ad575b60009561336e575b50926132ef612177612177612fe6896122db6132a3896000806132fd9f9b6132f79f9e8f6130ed9f60209f8f93613270612177612177612fe68561326a6132d4968d996132c99b50612e2b565b90612269565b94896132b0612fe663eab90da6956122db6132a3613298612fe68461326a60408a018a612e2b565b956040810190612e2b565b919092611a506001610de9565b90873b15613361575b6040519a8b998a98899760e01b90565b875260048701612edd565b03925af18015613354575b61332e575b506040810190612e2b565b6040516130c0565b96612ea6565b95613140565b61331b915060203d8111612cd957612ccb81836105f6565b38613101565b61332961213b565b6130f9565b6133479060005b61333f81836105f6565b810190610337565b386132e4565b503d613335565b61335c61213b565b6132df565b613369600080fd5b6132b9565b839550868593949592819260203d81116133a6575b61338d81836105f6565b8101613398916129aa565b97509250509392919361321d565b503d613383565b6133b561213b565b613215565b85859161319c565b9594936133fd9297506134039350612fe69150612fdc906133f36133eb61036e60208401612e21565b891015612f1f565b6040810190612e2b565b92612e21565b91836134386134327f9fc8352e52998db4087d5e6e1c1aafa38788e749e5d7a24f5cb230f73795440293611544565b93611544565b93613445611fe460405190565b0390a390565b61308592506134679060203d8111612cd957612ccb81836105f6565b91613050565b61347561213b565b613048565b61348d915061348888612e21565b613533565b6134c3816134a4612fe6612fdc60408a018a612e2b565b90856134bd6134b3600261201e565b92612c018d612e21565b92613573565b38612fc0565b506134d46001611592565b6134e16119d16000610de9565b11612fbb565b156134ee57565b60405162461bcd60e51b815260206004820152601b60248201527f59616b526f757465723a20496e73756666696369656e742066656500000000006044820152606490fd5b9061356e61036e92613543600090565b5061355c61355461036e6001611592565b8410156134e7565b612bec613567611259565b9384612783565b6127c0565b9291906135826117b530611544565b61358b82610355565b146135a15761359c61034a94611544565b613cf8565b506135ae61034a93611544565b613c90565b156135ba57565b60405162461bcd60e51b815260206004820152602860248201527f59616b526f757465723a2050617468206e6565647320746f20626567696e207760448201527f69746820574554480000000000000000000000000000000000000000000000006064820152608490fd5b90612e1e929161369361368e612fe66136876136556136476040870187612e2b565b93906000946122db86610de9565b613681612b517f00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b557610355565b146135b3565b8301612e21565b6136a2565b61369c30611544565b90612f91565b60006136ee6136d36121777f00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b557611544565b63d0e30db0813b15613725575b604051948593849260e01b90565b825281600481015b03925af18015613718575b6137085750565b61034a90600061333f81836105f6565b61372061213b565b613701565b61372d600080fd5b6136e0565b1561373957565b60405162461bcd60e51b815260206004820152602660248201527f59616b526f757465723a2050617468206e6565647320746f20656e642077697460448201527f68205745544800000000000000000000000000000000000000000000000000006064820152608490fd5b6138189061034a93926138086137d6612fe66040850161312e6122db6128666137cd848a612e2b565b9390948a612e2b565b613802612b517f00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b557610355565b14613732565b3361381230611544565b92612f91565b6138218161382e565b613829610dad565b61389c565b60006136f6916138606121777f00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b557611544565b61388183632e1a7d4d833b1561388f575b6040519687958694859360e01b90565b835260048301526024820190565b613897600080fd5b613871565b916138a630611544565b6138b2612b5183610355565b036138bc57505050565b6138c76117b5610dad565b6138d084610355565b0361390a57600080935080926138e96121778394611544565b828215613901575bf1156138f957565b61034a61213b565b506108fc6138f1565b6135ae61034a93611544565b949290979695939160e08601986000870161393091610388565b6020860161393d91610388565b6040850152606084015260ff16608083015260a082015260c00152565b929561034a96612fe693966139cc6139d787959861397b6040880188612e2b565b92909661399761217761217760009c8d9b8c986122db8a610de9565b9563d505accf9333986139b4876139ad30611544565b9d01612e21565b893b15613a18575b6040519c8d9b8c9a8b9960e01b90565b895260048901613916565b03925af18015613a0b575b6139ee575b5050612e11565b81613a0492903d1061334d5761333f81836105f6565b38806139e7565b613a1361213b565b6139e2565b613a20600080fd5b6139bc565b929561034a96612fe693966139cc613a4687959861397b6040880188612e2b565b03925af18015613a7a575b613a5d575b50506137a4565b81613a7392903d1061334d5761333f81836105f6565b3880613a56565b613a8261213b565b613a51565b61034a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab956115db565b61034a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95611728565b61034a903361058b565b61034a903390613afd613af6610df6565b91826115db565b6117a4565b61034a9190613b13611c9533611c6f565b613b64565b15613b1f57565b60405162461bcd60e51b815260206004820152601260248201527f4e6f7468696e6720746f207265636f76657200000000000000000000000000006044820152606490fd5b613b79613b716000610de9565b835b11613b18565b613b8d82613b8683611544565b3390613c90565b613bc4613bba7f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa2892611544565b926104c160405190565b0390a2565b9061034a91613b02565b61034a90613be3611c9533611c6f565b613b8d6000613bfa613bf482610de9565b84613b73565b8080808086613c0b61217733611544565b828215613c25575bf1610da457613c2061213b565b610da4565b506108fc613c13565b61034a90613bd3565b613c50613c4a61036e9263ffffffff1690565b60e01b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b91602061034a929493611f6460408201966000830190610388565b613cd3600492613cc461034a95613caa63a9059cbb613c37565b92613cb460405190565b9687946020860190815201613c75565b602082018103825203836105f6565b613f90565b604090611f6461034a949695939661213160608401986000850190610388565b90613cd390613cc461034a95600495613d146323b872dd613c37565b93613d1e60405190565b9788956020870190815201613cd8565b15613d3557565b60405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608490fd5b613cd3600492613cc461034a95613dcd600084613dbc82610de9565b8414918215613dda575b5050613d2e565b613caa63095ea7b3613c37565b9091506020613de889611544565b63dd62ed3e90613e14613dfa30611544565b92613e1f613e0760405190565b9788958694859460e01b90565b845260048401612028565b03915afa918215613e70575b600092613e48575b506119d1613e4091610de9565b148438613dc6565b613e40919250613e686119d19160203d8111612cd957612ccb81836105f6565b929150613e33565b613e7861213b565b613e2b565b3d15613e9757613e8c3d610e7b565b903d6000602084013e565b606090565b15613ea357565b60405162461bcd60e51b815280611709600482016020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b801515610403565b9050519061034a82613eec565b9061036e9160208183031215613ef457613f19600080fd5b613ef4565b15613f2557565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608490fd5b600091613f9d8392611544565b9082602082019151925af1613fb9613fb3613e7d565b91613e9c565b8051613fc86119d16000610de9565b11613fd05750565b613fec816020613fe161034a945190565b818301019101613f01565b613f1e565b9190604061401261400061255a565b9261400b8496614017565b8452614017565b910152565b90602091614027611a5684610de9565b92830152565b61403561255a565b5061036e6000820151916123a5602082015191614082604082015161407b6140636080606086015195015190565b9561407461406f612211565b998a52565b6020890152565b6040870152565b6060850152565b6116529061036e93926115f9565b6140b7929161034a916140a960405190565b948592602084019283614089565b908103825203836105f6565b90926103919360809361034a97966140ea60408601916140e4835191614017565b90614097565b90526140ff60208501916140e4835191614017565b905261411460008401916140e4835191614017565b905261412960608301916140e4835191614017565b90520191614135835190565b61191b565b61414261255a565b5061036e6141536000830151614219565b916123a56141646020830151614190565b916140826141756040830151614190565b61407b614063608061418a6060870151614190565b95015190565b908151916141a661265860209461288786610de9565b92836141b26000610de9565b6141c961036e6141c0865190565b61288786610de9565b8110156142125761420d906142086141fe6141f86141ef6141e988610de9565b856118f5565b611a5088610de9565b87015190565b612690838a6125d1565b612ea6565b6141b2565b5093505050565b9081519161422f61265860209461288786610de9565b928361423b6000610de9565b61424961036e6141c0865190565b81101561421257614276906142086142696141f86141ef6141e988610de9565b614273838a6125d1565b52565b61423b565b604061036e91614289600090565b500151805101519056fea26469706673582212209bab7ef2e02c88142d1a19cfb4bd54703a6e2d7623fefdd4d93a123ad69be2eb64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001bb7b44cc398aaa2b76ac6253f0f5634279db9d00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b5570000000000000000000000000000000000000000000000000000000000000003000000000000000000000000f05902d8eb53a354c9ddc67175df3d9bee1f95810000000000000000000000009cc2b9f9a6194c5cc827c88571e42ceaa76fdf4700000000000000000000000036049d5b4aaef6c39cd4a5bd1a2e1224f07621a20000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cf800f4948d16f23333508191b1b1591daf70438000000000000000000000000a2235d059f80e176d931ef76b6c51953eb3fbef400000000000000000000000048b62137edfa95a428d35c09e44256a739f6b557
-----Decoded View---------------
Arg [0] : _adapters (address[]): 0xF05902D8EB53a354c9dDC67175df3D9BEe1F9581,0x9CC2B9F9a6194C5CC827C88571E42cEAA76FDF47,0x36049d5B4aAef6c39Cd4a5bD1A2E1224F07621a2
Arg [1] : _trustedTokens (address[]): 0xcF800F4948D16F23333508191B1B1591daF70438,0xA2235d059F80e176D931Ef76b6C51953Eb3fBEf4,0x48b62137EdfA95a428D35C09E44256a739F6B557
Arg [2] : _feeClaimer (address): 0x01Bb7B44cc398AaA2b76Ac6253F0F5634279Db9D
Arg [3] : _wrapped_native (address): 0x48b62137EdfA95a428D35C09E44256a739F6B557
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [2] : 00000000000000000000000001bb7b44cc398aaa2b76ac6253f0f5634279db9d
Arg [3] : 00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b557
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [5] : 000000000000000000000000f05902d8eb53a354c9ddc67175df3d9bee1f9581
Arg [6] : 0000000000000000000000009cc2b9f9a6194c5cc827c88571e42ceaa76fdf47
Arg [7] : 00000000000000000000000036049d5b4aaef6c39cd4a5bd1a2e1224f07621a2
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [9] : 000000000000000000000000cf800f4948d16f23333508191b1b1591daf70438
Arg [10] : 000000000000000000000000a2235d059f80e176d931ef76b6c51953eb3fbef4
Arg [11] : 00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b557
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.