Source Code
Latest 25 from a total of 12,954 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Swap No Split To... | 199935662 | 654 days ago | IN | 0 ETH | 0.00000739 | ||||
| Swap No Split To... | 199920123 | 654 days ago | IN | 0 ETH | 0.00000733 | ||||
| Swap No Split | 199730503 | 655 days ago | IN | 0 ETH | 0.00000691 | ||||
| Swap No Split | 199729787 | 655 days ago | IN | 0 ETH | 0.00000458 | ||||
| Swap No Split Fr... | 199729461 | 655 days ago | IN | 0.09 ETH | 0.00001249 | ||||
| Swap No Split To... | 199728829 | 655 days ago | IN | 0 ETH | 0.00000466 | ||||
| Swap No Split Fr... | 199576569 | 655 days ago | IN | 0.03000843 ETH | 0.00000581 | ||||
| Swap No Split To... | 199562386 | 655 days ago | IN | 0 ETH | 0.00002539 | ||||
| Swap No Split To... | 199401510 | 656 days ago | IN | 0 ETH | 0.00000455 | ||||
| Swap No Split | 199229435 | 656 days ago | IN | 0 ETH | 0.00001325 | ||||
| Swap No Split | 199220508 | 656 days ago | IN | 0 ETH | 0.00001045 | ||||
| Swap No Split To... | 199215712 | 656 days ago | IN | 0 ETH | 0.00000134 | ||||
| Swap | 199215502 | 656 days ago | IN | 0 ETH | 0.00000222 | ||||
| Simple Swap | 199215210 | 656 days ago | IN | 0 ETH | 0.00000278 | ||||
| Swap No Split To... | 199214925 | 656 days ago | IN | 0 ETH | 0.00000192 | ||||
| Swap No Split To... | 199208572 | 656 days ago | IN | 0 ETH | 0.00000146 | ||||
| Swap No Split To... | 199208351 | 656 days ago | IN | 0 ETH | 0.00000148 | ||||
| Swap No Split To... | 199208318 | 656 days ago | IN | 0 ETH | 0.00000147 | ||||
| Swap No Split To... | 199208136 | 656 days ago | IN | 0 ETH | 0.00000146 | ||||
| Swap No Split To... | 199208091 | 656 days ago | IN | 0 ETH | 0.00000147 | ||||
| Swap No Split To... | 199207580 | 656 days ago | IN | 0 ETH | 0.00000146 | ||||
| Swap No Split To... | 199207545 | 656 days ago | IN | 0 ETH | 0.00000148 | ||||
| Swap No Split To... | 199206912 | 656 days ago | IN | 0 ETH | 0.00000151 | ||||
| Swap No Split To... | 199206625 | 656 days ago | IN | 0 ETH | 0.00000149 | ||||
| Swap No Split To... | 199206582 | 656 days ago | IN | 0 ETH | 0.00000148 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 199729461 | 655 days ago | 0.09 ETH | ||||
| 199576569 | 655 days ago | 0.03000843 ETH | ||||
| 199013746 | 657 days ago | 2.45 ETH | ||||
| 199013170 | 657 days ago | 8.3 ETH | ||||
| 199012701 | 657 days ago | 2.1 ETH | ||||
| 198958811 | 657 days ago | 0.17721166 ETH | ||||
| 198820828 | 657 days ago | 0.8258643 ETH | ||||
| 198445933 | 658 days ago | 0.08952917 ETH | ||||
| 198445771 | 658 days ago | 0.075 ETH | ||||
| 198438071 | 658 days ago | 0.36798842 ETH | ||||
| 198437936 | 658 days ago | 0.075 ETH | ||||
| 198435983 | 658 days ago | 0.36837179 ETH | ||||
| 198221038 | 659 days ago | 1 ETH | ||||
| 198137803 | 659 days ago | 0.01 ETH | ||||
| 198124025 | 659 days ago | 0.17697357 ETH | ||||
| 198090834 | 659 days ago | 1 ETH | ||||
| 198083415 | 659 days ago | 0.5 ETH | ||||
| 198055171 | 660 days ago | 0.5 ETH | ||||
| 198018683 | 660 days ago | 1.467 ETH | ||||
| 197993364 | 660 days ago | 0.2 ETH | ||||
| 197990136 | 660 days ago | 0.2 ETH | ||||
| 197985256 | 660 days ago | 0.2 ETH | ||||
| 197984798 | 660 days ago | 0.29 ETH | ||||
| 197983078 | 660 days ago | 0.2 ETH | ||||
| 197976504 | 660 days ago | 0.48999428 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CamelotYakRouter
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
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);
}
function _unwrapTo(address _to, uint256 _amount) internal {
IWETH(WNATIVE).withdrawTo(_to, _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) {
IAdapter _adapter = IAdapter(ADAPTERS[_index]);
try IAdapter(_adapter).query(_amountIn, _tokenIn, _tokenOut) returns (uint256 _amountOut) {
return _amountOut;
}
catch { return 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) {
if (i == 0 || amountOut > bestQuery.amountOut) {
bestQuery = Query(_adapter, _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) {
if (i == 0 || amountOut > bestQuery.amountOut) {
bestQuery = Query(_adapter, _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;
// Concatenate default and additional trusted tokens
address[] memory _allTrustedTokens = new address[](TRUSTED_TOKENS.length + _trustedTokens.length);
for (uint i=0; i < TRUSTED_TOKENS.length; i++) { _allTrustedTokens[i] = TRUSTED_TOKENS[i]; }
for (uint i=0; i < _trustedTokens.length; i++) { _allTrustedTokens[TRUSTED_TOKENS.length + i] = _trustedTokens[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);
// Concatenate default and additional trusted tokens
address[] memory _allTrustedTokens = new address[](TRUSTED_TOKENS.length + _trustedTokens.length);
for (uint i=0; i < TRUSTED_TOKENS.length; i++) { _allTrustedTokens[i] = TRUSTED_TOKENS[i]; }
for (uint i=0; i < _trustedTokens.length; i++) { _allTrustedTokens[TRUSTED_TOKENS.length + i] = _trustedTokens[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.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; i++) {
if (_tokenIn == _trustedTokens[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) {
continue;
}
// Explore options that connect the current path to the tokenOut
Offer memory newOffer = _queries.clone();
if (withGas) {
gasEstimate = IAdapter(bestSwap.adapter).swapGasEstimate();
}
newOffer.addToTail(bestSwap.amountOut, bestSwap.adapter, bestSwap.tokenOut, gasEstimate);
newOffer = _findBestPath(
bestSwap.amountOut,
_trustedTokens[i],
_tokenOut,
_trustedTokens,
_maxSteps,
newOffer,
_tknOutPriceNwei
); // Recursive step
address tokenOut = newOffer.getTokenOut();
uint256 amountOut = newOffer.getAmountOut();
// Check that the last token in the path is the tokenOut and update the new best option if neccesary
if (_tokenOut == tokenOut && amountOut > bestAmountOut) {
if (newOffer.gasEstimate > bestOption.gasEstimate) {
uint256 gasCostDiff = (_tknOutPriceNwei * (newOffer.gasEstimate - bestOption.gasEstimate)) /
1e9;
uint256 priceDiff = amountOut - bestAmountOut;
if (gasCostDiff > priceDiff) {
continue;
}
}
bestAmountOut = amountOut;
bestOption = newOffer;
}
}
}
return bestOption;
}
// -- SWAPPERS --
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);
}
_transferFrom(_trade.path[0], _from, _trade.adapters[0], amountIn);
address tokenOut = _trade.path[_trade.path.length - 1];
uint256 balanceBefore = IERC20(tokenOut).balanceOf(_to);
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.adapters[i + 1] : _to;
IAdapter(_trade.adapters[i]).swap(
amountIn,
0,
_trade.path[i],
_trade.path[i + 1],
targetAddress
);
amountIn = IERC20(_trade.path[i + 1]).balanceOf(targetAddress);
}
uint256 amountOut = amountIn - balanceBefore;
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));
_unwrapTo(_to, returnAmount);
}
/**
* 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.7.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IAdapter {
function name() external view returns (string memory);
function swapGasEstimate() external view returns (uint256);
function swap(
uint256,
uint256,
address,
address,
address
) external;
function query(
uint256,
address,
address
) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
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 withdrawTo(address account, uint256 amount) external;
function deposit() external payable;
}// ╟╗ ╔╬
// ╞╬╬ ╬╠╬
// ╔╣╬╬╬ ╠╠╠╠╦
// ╬╬╬╬╬╩ ╘╠╠╠╠╬
// ║╬╬╬╬╬ ╘╠╠╠╠╬
// ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╬╬╬╬╬╬╬╜ ╠╠╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╠
// ╙╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╕ ╬╬╬╬╬╬╬╜ ╣╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╩
// ╙╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╔╬╬╬╬╬╬╬ ╔╠╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬╬╬╬╬╠╠╠╠╝╙
// ╘╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╠╠╠╬╠╬╩╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╣╬╬╬╬╬╬╬╙
// ╣╬╬╬╬╬╬╬╬╬╬╠╣ ╣╬╠╠╠╬╩ ╚╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╣╬╬╬╬╬╬╬╬╬╣ ╣╬╠╠╠╬╬ ╣╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╟╬╬╬╬╬╬╬╩ ╬╬╠╠╠╠╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╠╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╒╬╬╠╠╬╠╠╬╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╬╬╬╠╠╠╠╝╝╝╝╝╝╝╠╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╚╬╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╣╬╬╬╬╠╠╩ ╘╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╙╬╬╬╬╬╬╬╬
//
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
struct Query {
address adapter;
address tokenIn;
address tokenOut;
uint256 amountOut;
}
struct Offer {
bytes amounts;
bytes adapters;
bytes path;
uint256 gasEstimate;
}
struct FormattedOffer {
uint256[] amounts;
address[] adapters;
address[] path;
uint256 gasEstimate;
}
struct Trade {
uint256 amountIn;
uint256 amountOut;
address[] path;
address[] adapters;
}
interface 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);
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.gasEstimate);
}
/**
* Appends new elements to the end of Offer struct
*/
function addToTail(
Offer memory _queries,
uint256 _amount,
address _adapter,
address _tokenOut,
uint256 _gasEstimate
) internal pure {
_queries.path = bytes.concat(_queries.path, _tokenOut.toBytes());
_queries.adapters = bytes.concat(_queries.adapters, _adapter.toBytes());
_queries.amounts = bytes.concat(_queries.amounts, _amount.toBytes());
_queries.gasEstimate += _gasEstimate;
}
/**
* Formats elements in the Offer object from byte-arrays to integers and addresses
*/
function format(Offer memory _queries) internal pure returns (FormattedOffer memory) {
return
FormattedOffer(
_queries.amounts.toUints(),
_queries.adapters.toAddresses(),
_queries.path.toAddresses(),
_queries.gasEstimate
);
}
function getTokenOut(
Offer memory _offer
) internal pure returns (address tokenOut) {
tokenOut = _offer.path.toAddress(_offer.path.length); // Last 32 bytes
}
function getAmountOut(
Offer memory _offer
) internal pure returns (uint amountOut) {
amountOut = _offer.amounts.toUint(_offer.path.length); // Last 32 bytes
}
}
library FormattedOfferUtils {
using TypeConversion for address;
using TypeConversion for uint256;
using TypeConversion for bytes;
/**
* Appends new elements to the end of FormattedOffer
*/
function addToTail(
FormattedOffer memory offer,
uint256 amountOut,
address wrapper,
address tokenOut,
uint256 gasEstimate
) internal pure {
offer.amounts = bytes.concat(abi.encodePacked(offer.amounts), amountOut.toBytes()).toUints();
offer.adapters = bytes.concat(abi.encodePacked(offer.adapters), wrapper.toBytes()).toAddresses();
offer.path = bytes.concat(abi.encodePacked(offer.path), tokenOut.toBytes()).toAddresses();
offer.gasEstimate += gasEstimate;
}
/**
* Appends new elements to the beginning of FormattedOffer
*/
function addToHead(
FormattedOffer memory offer,
uint256 amountOut,
address wrapper,
address tokenOut,
uint256 gasEstimate
) internal pure {
offer.amounts = bytes.concat(amountOut.toBytes(), abi.encodePacked(offer.amounts)).toUints();
offer.adapters = bytes.concat(wrapper.toBytes(), abi.encodePacked(offer.adapters)).toAddresses();
offer.path = bytes.concat(tokenOut.toBytes(), abi.encodePacked(offer.path)).toAddresses();
offer.gasEstimate += gasEstimate;
}
function getAmountOut(FormattedOffer memory offer) internal pure returns (uint256) {
return offer.amounts[offer.amounts.length - 1];
}
}{
"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":"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":"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"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"uint8[]","name":"_options","type":"uint8[]"}],"name":"queryNoSplit","outputs":[{"components":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"internalType":"struct Query","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"}],"name":"queryNoSplit","outputs":[{"components":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"internalType":"struct Query","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"removedMaintainer","type":"address"}],"name":"removeMaintainer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_adapters","type":"address[]"}],"name":"setAdapters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wnative","type":"address"}],"name":"setAllowanceForWrapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_claimer","type":"address"}],"name":"setFeeClaimer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setMinFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_trustedTokens","type":"address[]"}],"name":"setTrustedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address[]","name":"adapters","type":"address[]"}],"internalType":"struct Trade","name":"_trade","type":"tuple"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"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":"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":"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":"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":"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
60a06040523462000061575b620000236200001962000262565b92919091620002cb565b604051613ff862000cc18239608051818181610f820152818161273d01528181613453015281816134a5015281816135d4015261363a0152613ff890f35b6200006a600080fd5b6200000b565b600080fd5b50634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b03821117620000ae57604052565b620000b862000075565b604052565b90620000d4620000cc60405190565b92836200008c565b565b60209081906001600160401b038111620000ef57020190565b620000f962000075565b020190565b6001600160a01b031690565b90565b6001600160a01b0381165b036200007057565b90505190620000d4826200010d565b90929192620001486200014282620000d6565b620000bd565b93818552602080860192028301928184116200018b575b915b8383106200016f5750505050565b602080916200017f848662000120565b81520192019162000161565b62000194600080fd5b6200015f565b906200010a9181601f82011215620001b9575b6020815191016200012f565b620001c2600080fd5b620001ad565b60808183031262000253575b8051620001f59083906001600160401b03811162000244575b83016200019a565b926200010a6200021b84602085015160018060401b03811162000235575b85016200019a565b936200022b816040860162000120565b9360600162000120565b6200023e600080fd5b62000213565b6200024d600080fd5b620001ed565b6200025c600080fd5b620001d4565b6200028562004cd9803803806200027981620000bd565b928339810190620001c8565b90919293565b90600019905b9181191691161790565b6200010a6200010a6200010a9290565b90620002bf6200010a620002c7926200029b565b82546200028b565b9055565b906200030f92620003036200030992620002e462000314565b620002f260006001620002ab565b620002fd876200052c565b62000769565b620008a9565b620007d0565b608052565b620000d4620000d46200032e565b6200010a60006200029b565b620000d43362000348816200034262000322565b62000359565b60008051602062004cb98339815191525b90620000d491620003d2565b905b600052602052604060002090565b6200010a90620000fe906001600160a01b031682565b6200010a9062000375565b6200010a906200038b565b90620003679062000396565b9060ff9062000291565b90620003ca6200010a620002c792151590565b8254620003ad565b90620003e7620003e3828462000461565b1590565b620003f0575050565b6200041660016200041083600062000409878262000365565b01620003a1565b620003b7565b33906200045062000449620004497f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9590565b9262000396565b926200045b60405190565b600090a4565b6200010a916200047991620004096000918262000365565b5460ff1690565b0190565b156200048c57565b60405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201526734b73a30b4b732b960c11b6064820152608490fd5b0390fd5b620000d490620005116200050b335b60008051602062004cb983398151915262000461565b62000484565b620000d490620005218162000396565b6000199190620009b2565b620000d490620004e6565b620000d4906200054b6200050b33620004f5565b62000721565b90620005746200056d62000563845190565b8084529260200190565b9260200190565b9060005b818110620005865750505090565b909192620005ae620005a760019286516001600160a01b0316815260200190565b9460200190565b92910162000578565b60208082526200010a9291019062000551565b9160001960089290920291821b911b62000291565b9190620005f46200010a620002c7936200029b565b908354620005ca565b620000d491600091620005df565b81811062000617575050565b80620006276000600193620005fd565b016200060b565b90918281106200063d57505050565b620000d4929062000655905b92600052602060002090565b90810191016200060b565b90620000d49168010000000000000000821162000684575b8054908281556200062e565b6200068e62000075565b62000678565b6001620006c862000649620006a7855190565b94838060401b03861162000705575b620006c2868662000660565b60200190565b92049160005b838110620006dc5750505050565b6001906020620006f76200010a86516001600160a01b031690565b9401938184015501620006ce565b6200070f62000075565b620006b6565b90620000d49162000694565b620000d4907f658ff1688002926d8f426cb10c052ec29003f50042df9652d8613484c1a586476200075160405190565b806200075e8482620005b7565b0390a1600362000715565b620000d49062000537565b620000d490620007886200050b33620004f5565b620000d4907febf7325f48e05e5e38809c69f8b02a7c907ed31d8768e6c2d841b1296a9225fe620007b860405190565b80620007c58482620005b7565b0390a1600462000715565b620000d49062000774565b620000d490620007ef6200050b33620004f5565b62000852565b6200010a90620000fe565b6200010a9054620007f5565b6001600160a01b0391821681529116602082015260400190565b906001600160a01b039062000291565b906200084a6200010a620002c79262000396565b825462000826565b620000d49062000863600262000800565b817fb2c853ac4d80d18d058c43d8018d077a036e542a79acae1647f5ad2a8c76f4e2916200089e6200089460405190565b928392836200080c565b0390a1600262000836565b620000d490620007db565b8062000118565b90505190620000d482620008b4565b906200010a9160208183031215620008bb57620008e5600080fd5b620008bb565b506040513d6000823e3d90fd5b156200090057565b60405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608490fd5b62000987620009816200010a9263ffffffff1690565b60e01b90565b6001600160e01b03191690565b6001600160a01b039091168152604081019291620000d49160200152565b62000a2260049262000a12620000d495620009e7600084620009d4826200029b565b841491821562000a28575b5050620008f8565b620009f663095ea7b36200096b565b9262000a0160405190565b968794602086019081520162000994565b602082018103825203836200008c565b62000c50565b909150602062000a388962000396565b63dd62ed3e9062000a6962000a4d3062000396565b9262000a7562000a5c60405190565b9788958694859460e01b90565b8452600484016200080c565b03915afa91821562000ae9575b60009262000aa8575b5062000a9b62000a9f916200029b565b9190565b148438620009df565b62000a9f91925062000ad862000a9b9160203d811162000ae1575b62000acf81836200008c565b810190620008ca565b92915062000a8b565b503d62000ac3565b62000af3620008eb565b62000a82565b60209062000480906001600160401b03811162000b1a57601f01601f191690565b62000b2462000075565b601f01601f191690565b9062000b3e620001428362000af9565b918252565b3d1562000b605762000b553d62000b2e565b903d6000602084013e565b606090565b1562000b6d57565b60405162461bcd60e51b815280620004e2600482016020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b80151562000118565b90505190620000d48262000bb7565b906200010a916020818303121562000bc05762000bea600080fd5b62000bc0565b1562000bf857565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b60009162000c5f839262000396565b9082602082019151925af162000c7f62000c7862000b43565b9162000b65565b805162000c9162000a9b60006200029b565b1162000c9a5750565b62000cba81602062000cae620000d4945190565b81830101910162000bcf565b62000bf056fe6080604052600436101561001e575b361561001c5761001c600080fd5b005b60003560e01c8062b99e361461032957806301ffc9a714610320578063248a9ca3146103175780632f2ff15d1461030e57806331ac99201461030557806336568abe146102fc57806338a3374f146102f357806339b85456146102ea5780633a9a4081146102e157806352a52ab0146102d85780636b453c1f146102cf57806376c7a3c7146102c657806376ebe69c146102bd5780637c7a561b146102b4578063809356aa146102ab57806386e450d1146102a25780638980f11f146102995780638bb9c5bf1461029057806391d148541461028757806392f5d88a1461027e578063952e901214610275578063996d6f701461026c578063a0cf0aea14610263578063a217fddf1461025a578063a3f4df7e14610251578063aede369314610248578063b381cf401461023f578063b9a89ca314610236578063c3accd481461022d578063c8a3a5c614610224578063d547741f1461021b578063d73792a914610212578063d8baf7cf14610209578063dd8544b314610200578063dede7f15146101f7578063f2fde38b146101ee578063f6ee13a6146101e5578063f8742254146101dc5763faa3f2f90361000e576101d76113f2565b61000e565b506101d76113aa565b506101d7611379565b506101d76112ca565b506101d761129f565b506101d7611243565b506101d761121c565b506101d76111f2565b506101d76111b7565b506101d7611190565b506101d7611169565b506101d761112f565b506101d7610f6b565b506101d7610f44565b506101d7610f0e565b506101d7610de0565b506101d7610d97565b506101d7610d41565b506101d7610d17565b506101d7610cd1565b506101d7610b96565b506101d7610b6f565b506101d7610b47565b506101d7610aee565b506101d7610ac0565b506101d7610a4b565b506101d7610a20565b506101d76109f6565b506101d76109ad565b506101d7610966565b506101d76108a9565b506101d76106d1565b506101d7610612565b506101d7610576565b506101d761054f565b506101d7610522565b506101d76104a0565b506101d7610434565b506101d76103a5565b600080fd5b600091031261034257565b61034a600080fd5b565b61036e916008021c5b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b9061036e915461034c565b61036e60006002610371565b61039190610355565b9052565b60208101929161034a9190610388565b50346103d2575b6103b7366004610337565b6103ce6103c261037c565b60405191829182610395565b0390f35b6103da600080fd5b6103ac565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b0361033257565b9050359061034a826103df565b9061036e916020818303121561040a5761042f600080fd5b61040a565b5034610463575b6103ce61045161044c366004610417565b61141a565b60405191829182901515815260200190565b61046b600080fd5b61043b565b80610403565b9050359061034a82610470565b9061036e91602081830312156104765761049b600080fd5b610476565b50346104ce575b6103ce6104bd6104b8366004610483565b61154a565b6040515b9182918290815260200190565b6104d6600080fd5b6104a7565b61040381610355565b9050359061034a826104db565b919061036e90604084820312610515575b61050c8185610476565b936020016104e4565b61051d600080fd5b610502565b5034610542575b61053d6105373660046104f1565b90611589565b604051005b61054a600080fd5b610529565b5034610569575b61053d610564366004610483565b611f6a565b610571600080fd5b610556565b5034610591575b61053d61058b3660046104f1565b9061178c565b610599600080fd5b61057d565b908160809103126105ac5790565b61036e600080fd5b9091606082840312610605575b61036e6105e184843567ffffffffffffffff81116105f8575b850161059e565b936105ef8160208601610476565b936040016104e4565b610600600080fd5b6105da565b61060d600080fd5b6105c1565b5061053d6106213660046105b4565b9161341b565b60ff8116610403565b9050359061034a82610627565b60e0818303126106c4575b61066582823567ffffffffffffffff81116106b7575b830161059e565b926106738360208401610476565b9261068181604085016104e4565b9261068f8260608301610476565b9261036e6106a08460808501610630565b936106ae8160a08601610476565b9360c001610476565b6106bf600080fd5b61065e565b6106cc600080fd5b610648565b50346106f2575b61053d6106e636600461063d565b959490949391936137af565b6106fa600080fd5b6106d8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810190811067ffffffffffffffff82111761079757604052565b61079f610727565b604052565b9061034a6107b160405190565b9283610757565b6020809167ffffffffffffffff81116107d057020190565b6107d8610727565b020190565b909291926107f26107ed826107b8565b6107a4565b9381855260208086019202830192818411610830575b915b8383106108175750505050565b6020809161082584866104e4565b81520192019161080a565b610838600080fd5b610808565b9061036e9181601f82011215610859575b6020813591016107dd565b610861600080fd5b61084e565b9061036e9160208183031261089c575b80359067ffffffffffffffff821161088f575b0161083d565b610897600080fd5b610889565b6108a4600080fd5b610876565b50346108c3575b61053d6108be366004610866565b611ea6565b6108cb600080fd5b6108b0565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b61092060019161090e815490565b84101561092957600052602060002090565b91020190600090565b6109316108d0565b600052602060002090565b60036000610948825490565b831015610963575061036e9161095d91610900565b90610371565b80fd5b5034610983575b6103ce6103c261097e366004610483565b61093c565b61098b600080fd5b61096d565b9061036e91602081830312156104e4576109a8600080fd5b6104e4565b50346109c7575b61053d6109c2366004610990565b613811565b6109cf600080fd5b6109b4565b61036e916008021c81565b9061036e91546109d4565b61036e600060016109df565b5034610a13575b610a08366004610337565b6103ce6104bd6109ea565b610a1b600080fd5b6109fd565b5034610a3e575b610a32366004610337565b6103ce6104bd60035490565b610a46600080fd5b610a27565b5034610a69575b610a5d366004610337565b6103ce6104bd60045490565b610a71600080fd5b610a52565b608081830312610ab3575b610a8b8282610476565b9261036e610a9c84602085016104e4565b93610aaa81604086016104e4565b93606001610630565b610abb600080fd5b610a81565b5034610ae1575b6103ce6104bd610ad8366004610a76565b929190916120a1565b610ae9600080fd5b610ac7565b5034610b09575b61053d610b033660046105b4565b91612d09565b610b11600080fd5b610af5565b919061036e90604084820312610b3a575b610b3181856104e4565b93602001610476565b610b42600080fd5b610b27565b5034610b62575b61053d610b5c366004610b16565b90613953565b610b6a600080fd5b610b4e565b5034610b89575b61053d610b84366004610483565b613865565b610b91600080fd5b610b76565b5034610bb4575b6103ce610451610bae3660046104f1565b9061151a565b610bbc600080fd5b610b9d565b909182601f83011215610c00575b602082359267ffffffffffffffff8411610bf3575b01926020830284011161034257565b610bfb600080fd5b610be4565b610c08600080fd5b610bcf565b608081830312610c6f575b610c228282610476565b92610c5e610c3384602085016104e4565b93610c4181604086016104e4565b9360608101359067ffffffffffffffff8211610c62575b01610bc1565b9091565b610c6a600080fd5b610c58565b610c77600080fd5b610c18565b9060608061034a93610c9660008201516000860190610388565b610ca860208201516020860190610388565b610cba60408201516040860190610388565b0151910152565b60808101929161034a9190610c7c565b5034610cfe575b6103ce610cf2610ce9366004610c0d565b939290926121d8565b60405191829182610cc1565b610d06600080fd5b610cd8565b60046000610948825490565b5034610d34575b6103ce6103c2610d2f366004610483565b610d0b565b610d3c600080fd5b610d1e565b5034610d62575b61053d610d5636600461063d565b959490949391936136e4565b610d6a600080fd5b610d48565b61035561036e61036e9290565b61036e90610d6f565b61036e6000610d7c565b61036e610d85565b5034610db4575b610da9366004610337565b6103ce6103c2610d8f565b610dbc600080fd5b610d9e565b61036e61036e61036e9290565b61036e6000610dc1565b61036e610dce565b5034610dfd575b610df2366004610337565b6103ce6104bd610dd8565b610e05600080fd5b610de7565b610e4760209167ffffffffffffffff8111610e4b57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690565b0190565b6106ff610727565b90610e606107ed83610e0a565b918252565b610e6f6010610e53565b7f43616d656c6f7459616b526f7574657200000000000000000000000000000000602082015290565b61036e610e65565b61036e610e98565b61036e610ea0565b60005b838110610ec35750506000910152565b8181015183820152602001610eb3565b610ef46106ff602093610e4793610ee8815190565b80835293849260200190565b95869101610eb0565b602080825261036e92910190610ed3565b5034610f37575b610f20366004610337565b6103ce610f2b610ea8565b60405191829182610efd565b610f3f600080fd5b610f15565b5034610f5e575b61053d610f59366004610483565b6139b8565b610f66600080fd5b610f4b565b5034610fa6575b610f7d366004610337565b6103ce7f00000000000000000000000000000000000000000000000000000000000000006103c2565b610fae600080fd5b610f72565b919060a083820312611020575b610fca8184610476565b92610fd882602083016104e4565b9261036e610fe984604085016104e4565b9361100a81606086013567ffffffffffffffff8111611013575b860161083d565b93608001610476565b61101b600080fd5b611003565b611028600080fd5b610fc0565b9061104d61104661103c845190565b8084529260200190565b9260200190565b9060005b81811061105e5750505090565b90919261107b6110746001928651815260200190565b9460200190565b929101611051565b90610e4781602093610388565b9061109f61104661103c845190565b9060005b8181106110b05750505090565b9091926110c36110746001928651611083565b9291016110a3565b9061036e906060806111166111046110f2608086016000890151878203600089015261102d565b60208801518682036020880152611090565b60408701518582036040870152611090565b940151910152565b602080825261036e929101906110cb565b503461115c575b6103ce611150611147366004610fb3565b939290926127e4565b6040519182918261111e565b611164600080fd5b611136565b5034611183575b61053d61117e366004610990565b612040565b61118b600080fd5b611170565b50346111aa575b61053d6111a5366004610866565b611e4a565b6111b2600080fd5b611197565b50346111d2575b61053d6111cc3660046104f1565b90611710565b6111da600080fd5b6111be565b61036e612710610dc1565b61036e6111df565b503461120f575b611204366004610337565b6103ce6104bd6111ea565b611217600080fd5b6111f9565b5034611236575b61053d611231366004610990565b61383b565b61123e600080fd5b611223565b503461125d575b61053d611258366004610990565b611c42565b611265600080fd5b61124a565b9091606082840312611292575b61036e6112848484610476565b936105ef81602086016104e4565b61129a600080fd5b611277565b50346112bd575b6103ce610cf26112b736600461126a565b91612327565b6112c5600080fd5b6112a6565b50346112e4575b61053d6112df366004610990565b61386f565b6112ec600080fd5b6112d1565b909160c08284031261136c575b6113088383610476565b9261131681602085016104e4565b9261132482604083016104e4565b9261036e61134884606085013567ffffffffffffffff811161135f575b850161083d565b936113568160808601610476565b9360a001610476565b611367600080fd5b611341565b611374600080fd5b6112fe565b503461139d575b6103ce6111506113913660046112f1565b94939093929192612532565b6113a5600080fd5b611380565b50346113e5575b6113bc366004610337565b6103ce7f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab956104bd565b6113ed600080fd5b6113b1565b503461140d575b61053d6114073660046105b4565b9161359a565b611415600080fd5b6113f9565b7f7965db0b000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082161490811561146a575090565b61036e91507fffffffff00000000000000000000000000000000000000000000000000000000167f01ffc9a7000000000000000000000000000000000000000000000000000000001490565b905b600052602052604060002090565b61035561036e61036e9273ffffffffffffffffffffffffffffffffffffffff1690565b61036e906114c6565b61036e906114e9565b906114b8906114f2565b61036e905b60ff1690565b61036e9054611505565b61036e916115349161152e600091826114b6565b016114fb565b611510565b61036e9081565b61036e9054611539565b600161156361036e9261155b600090565b5060006114b6565b01611540565b9061034a9161157f61157a8261154a565b611593565b9061034a916117e0565b9061034a91611569565b61034a903390611652565b61036e61036e61036e9273ffffffffffffffffffffffffffffffffffffffff1690565b61036e90610dc1565b610e476115e2926020926115dc815190565b94859290565b93849101610eb0565b61162961036e9392611623611623937f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260170190565b906115ca565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000815260110190565b90611664611660828461151a565b1590565b61166c575050565b6116f19161036e6116a561169f6116856116d9956114e9565b61169961169360149261159e565b91610dc1565b90611a07565b926115c1565b6116b460209161169983610dc1565b926116cd6116c160405190565b948593840192836115eb565b90810382520382610757565b60405191829162461bcd60e51b835260048301610efd565b0390fd5b9061034a9161170661157a8261154a565b9061034a91611856565b9061034a916116f5565b1561172157565b60405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608490fd5b61034a91906117b16117a233610355565b610355565b6117ab84610355565b1461171a565b611856565b9060ff905b9181191691161790565b906117d561036e6117dc92151590565b82546117b6565b9055565b906117ee611660828461151a565b6117f6575050565b611810600161180b83600061152e87826114b6565b6117c5565b33906118466118406118407f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9590565b926114f2565b9261185060405190565b600090a4565b90611861818361151a565b611869575050565b61187d600061180b838261152e87826114b6565b33906118466118406118407ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9590565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818102929181159184041417156118f057565b61034a6118ad565b919082018092116118f057565b369037565b9061034a61192061191a84610e53565b93610e0a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00160208401611905565b906001602091611959845190565b811015611967575b02010190565b61196f6108d0565b611961565b6001908015611981570390565b6119896118ad565b0390565b61150a61036e61036e9290565b61036e906119b26119ae61036e9460ff1690565b9190565b901c90565b156119be57565b60405162461bcd60e51b8152806116f1600482016020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b9190600290611a38611a33611a2483611a1f86610dc1565b6118dd565b611a2d85610dc1565b906118f8565b61190a565b916000916030611a50611a4a85610dc1565b8661194b565b53611aa4611a9b7f780000000000000000000000000000000000000000000000000000000000000092611a1f6001958695881a611a95611a8f88610dc1565b8b61194b565b53610dc1565b611a2d83610dc1565b915b611ac7575b505061036e9293611ac16119ae61036e93610dc1565b146119b7565b9094611ad282610dc1565b861115611b5e57611b4b611b458392611b28611b0b7f303132333435363738396162636465660000000000000000000000000000000090565b611b15600f610dc1565b83166010811015611b51575b1a60f81b90565b861a611b348a8961194b565b53611b3f600461198d565b9061199a565b96611974565b91611aa6565b611b596108d0565b611b21565b94611aab565b15611b6b57565b60405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201527f696e7461696e65720000000000000000000000000000000000000000000000006064820152608490fd5b61034a90611c0d611c08335b7f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab9561151a565b611b64565b61034a90611c1a816114f2565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91613b0f565b61034a90611bd6565b61034a90611c5b611c0833611be2565b611e07565b90611c6f61104661103c845190565b9060005b818110611c805750505090565b909192611c936110746001928651611083565b929101611c73565b602080825261036e92910190611c60565b919060086117bb910291611cdf7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841b90565b921b90565b9190611cf561036e6117dc93610dc1565b908354611cac565b61034a91600091611ce4565b818110611d14575050565b80611d226000600193611cfd565b01611d09565b9091828110611d3657505050565b61034a9290611d4c905b92600052602060002090565b9081019101611d09565b9061034a91680100000000000000008211611d77575b805490828155611d28565b611d7f610727565b611d6c565b61036e9051610355565b6001611dbf611d40611d9e855190565b9467ffffffffffffffff8611611df0575b611db98686611d56565b60200190565b92049160005b838110611dd25750505050565b6001906020611de361036e86611d84565b9401938184015501611dc5565b611df8610727565b611daf565b9061034a91611d8e565b61034a907f658ff1688002926d8f426cb10c052ec29003f50042df9652d8613484c1a58647611e3560405190565b80611e408482611c9b565b0390a16003611dfd565b61034a90611c4b565b61034a90611e63611c0833611be2565b61034a907febf7325f48e05e5e38809c69f8b02a7c907ed31d8768e6c2d841b1296a9225fe611e9160405190565b80611e9c8482611c9b565b0390a16004611dfd565b61034a90611e53565b61034a90611ebf611c0833611be2565b611f1a565b90815260408101929161034a9160200152565b0152565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff906117bb565b90611f1361036e6117dc92610dc1565b8254611edb565b61034a90611f286001611540565b817f4bb8a6184424e4bb853a4836042f5a726e4e710873989bfc6abdab19966f5b7091611f60611f5760405190565b92839283611ec4565b0390a16001611f03565b61034a90611eaf565b61034a90611f83611c0833611be2565b611ff0565b61036e90610355565b61036e9054611f88565b91602061034a929493611fb660408201966000830190610388565b0190610388565b9073ffffffffffffffffffffffffffffffffffffffff906117bb565b90611fe961036e6117dc926114f2565b8254611fbd565b61034a90611ffe6002611f91565b817fb2c853ac4d80d18d058c43d8018d077a036e542a79acae1647f5ad2a8c76f4e29161203661202d60405190565b92839283611f9b565b0390a16002611fd9565b61034a90611f73565b9050519061034a82610470565b9061036e91602081830312156120495761206e600080fd5b612049565b90815260608101939261034a929091604091611fb6905b6020830190610388565b506040513d6000823e3d90fd5b919260209194936120ee6120b3600090565b966120f76120d16120cc6120cc61095d60049889610900565b6114f2565b9363ef99893a926120e160405190565b9889978896879660e01b90565b86528501612073565b03915afa6000918161211a575b506121165750905061036e6000610dc1565b9150565b61213c91925060203d8111612143575b6121348183610757565b810190612056565b9038612104565b503d61212a565b61036e60806107a4565b61215c61214a565b906000825260208080808501600081520160005b8152016000905250565b61036e612154565b60019060ff1660ff8114612194570190565b610e476118ad565b61036e61036e61036e9260ff1690565b916020918110156121bc57020190565b6107d86108d0565b3561036e81610627565b9061039190610355565b9094939192946121e661217a565b506121ef61217a565b9360005b846121fd8261219c565b101561231d57600484602061223061095d61222a6122258e8c61221f8a61219c565b916121ac565b6121c4565b85610900565b9261223d6120cc856114f2565b6120ee63ef99893a612253898b6120e160405190565b03915afa600091816122fd575b50612276575050612271905b612182565b6121f3565b6000916122828361198d565b60ff85161480156122e7575b61229f575b50505061227190612182565b612271939850906122bd6122de926122b561214a565b9485016121ce565b6122ca86602085016121ce565b6122d785604085016121ce565b6060830152565b95903880612293565b506122f661036e60608b015190565b821161228e565b61231691925060203d8111612143576121348183610757565b9038612260565b5093955050505050565b909161233161217a565b5061233a61217a565b9160005b600461234b61036e825490565b6123548361219c565b101561244d5782602061236a61095d8585610900565b926123776120cc856114f2565b6120ee63ef99893a61238d8a8d6120e160405190565b03915afa6000918161242d575b506123b55750506123b090600161226c57612182565b61233e565b6000916123c18361198d565b60ff8516148015612417575b6123de575b5050506123b090612182565b6123b0939650906123f461240e926122b561214a565b61240188602085016121ce565b6122d786604085016121ce565b939038806123d2565b5061242661036e606089015190565b82116123cd565b61244691925060203d8111612143576121348183610757565b903861239a565b50505050905090565b61245e61214a565b90606082526020808080850160608152016060612170565b61036e612456565b1561248557565b60405162461bcd60e51b815260206004820152601c60248201527f59616b526f757465723a20496e76616c6964206d61782d7374657073000000006044820152606490fd5b90610e606107ed836107b8565b9061034a6119206124e7846124ca565b936107b8565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612194570190565b9060208091611959845190565b61036e6000610e53565b929195909461253f612476565b5060009061254c82610dc1565b8611806126c3575b61255d9061247e565b6125678786613d60565b908861257284610dc1565b600092908111156126b257612587925061272d565b905b6003966125a66125a161259a8a5490565b8851611a2d565b6124d7565b996125b085610dc1565b8b6125bc61036e8c5490565b8210156125f257906125e86125ed926125e3836125dd8f8261095d91610900565b9261251b565b6121ce565b6124ed565b6125b0565b5050909192939495969861260586610dc1565b61261061036e8a5190565b81101561265257806125e88b6125e38f612647858f61263d61263861264d9a6126429361251b565b611d84565b955490565b6118f8565b9061251b565b612605565b5090919395999294975061266a965061036e9861290f565b9061267760208301515190565b6126836119ae83610dc1565b1461268f575b50613e7e565b61269d908201610391612528565b6126ac60408201610391612528565b38612689565b50506126bd90610dc1565b90612589565b5061255d6126d16005610dc1565b87109050612554565b919082039182116118f057565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8115612721570490565b6127296126e7565b0490565b90919061277c60009360606002917f0000000000000000000000000000000000000000000000000000000000000000612776612770670de0b6b3a7640000610dc1565b94610dc1565b936127e4565b604081015151906000916127926119ae84610dc1565b0361279c57505050565b61036e9394506127cd6127d19392611a1f92016126476127bd825192515190565b6127c76001610dc1565b906126da565b5190565b6127de633b9aca00610dc1565b90612717565b949290926127f0612476565b506000936127fd85610dc1565b8611806128f8575b61280e9061247e565b6128188188613d60565b946003976128316125a161282a8b5490565b8751611a2d565b9661283b83610dc1565b8a61284761036e825490565b82101561287157906125e861286261095d8361286c95610900565b6125e3838d61251b565b61283b565b50509091929394959761288384610dc1565b61288e61036e895190565b8110156128c557806125e88c6125e36128ba846126426128b58f6128c0996126389161251b565b945490565b8d61251b565b612883565b50919396909295506128e894985061036e976128e087610dc1565b97889561290f565b9161268361036e60208501515190565b5061280e6129066005610dc1565b87109050612805565b9192909395949561291e612476565b5061292887613d9c565b918297612933600090565b94859060009061294282610dc1565b8b1415966129518a8c84612327565b90606082019161295f835190565b61296b6119ae87610dc1565b03612c55575b5050506001996129808b610dc1565b871180612c1b575b61299c575b50505050505050505050505090565b9082916129aa8c9594610dc1565b945b6129b7575b5061298d565b6129c261036e885190565b851015612c1657846129db61179d6126388e988b61251b565b6129e483610355565b14612c08578d8a8a8a612a046129fd612638878461251b565b8789612327565b9960608b019a612a128c5190565b612a1e6119ae8c610dc1565b14612bf457612a2c8d613d9c565b94612b5e575b8b6127cd8c8c612a7e9a9b9c9d9e9f94612a646040612a5d612a55612a6b995190565b948401611d84565b9201611d84565b918a613e23565b612a78612638898561251b565b9061290f565b612a8781613faa565b8c612aac612aa6612aa085805160409091015151015190565b93610355565b91610355565b1480612b55575b612acd575b5050612ac3906124ed565b939291908b6129ac565b919e909a8e60608d01612ade815190565b906060850191612af26119ae61036e855190565b11612b0a575b5050505050612ac390999d9038612ab8565b91612b256127d1926127c7612b20612b2b965190565b915190565b906118dd565b612b3b6119ae61036e84876126da565b11612b48578e8180612af8565b9a509d612ac391506124ed565b508b8111612ab3565b899b8a9b506127cd82612b9f6020612b87612a7e9c9d9e9f6120cc6120cc91612a6b9901611d84565b6369cff80d90612b9660405190565b93849260e01b90565b825260049082905afa908115612be7575b600091612bc9575b509d509250509b9998979650612a32565b612be1915060203d8111612143576121348183610757565b38612bb8565b612bef612094565b612bb0565b505050505050612ac39192939495506124ed565b612ac39192939495506124ed565b6129b1565b50612c35612c2b60208701515190565b6127de6020610dc1565b612c4e6119ae61036e612c486002610dc1565b8b6126da565b1115612988565b909192995088612c98575b8483926127cd92612c72612c8f965190565b612c896040612c828a8501611d84565b9301611d84565b92613e23565b96388080612971565b612c8f9291945080612cb96020612b876120cc6120cc896127cd9701611d84565b825260049082905afa908115612cfc575b600091612cde575b50959293509050612c60565b612cf6915060203d8111612143576121348183610757565b38612cd2565b612d04612094565b612cca565b90612d1692913390612e5b565b50565b3561036e81610470565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe13682900301821215612d87575b01602081359167ffffffffffffffff8311612d7a575b0191602082023603831361034257565b612d82600080fd5b612d6a565b612d8f600080fd5b612d54565b3561036e816104db565b61039190610dc1565b9095949261034a94612ddf611fb692612dd5608096612dcb60a088019c6000890152565b6020870190612d9e565b6040850190610388565b6060830190610388565b15612df057565b60405162461bcd60e51b815260206004820152602560248201527f59616b526f757465723a20496e73756666696369656e74206f7574707574206160448201527f6d6f756e740000000000000000000000000000000000000000000000000000006064820152608490fd5b93849391612e6885612d19565b93612e736000610dc1565b811180156132bf575b613261575b5083612ec391612ea9612ea4612e9a60408b018b612d23565b61221f6000610dc1565b612d94565b90612ebd612ea4612e9a60608c018c612d23565b91613369565b612eee612ea4612ed66040880188612d23565b61221f6127bd612ee960408c018c612d23565b905090565b93612efb6120cc866114f2565b946020612f0760405190565b9687907f70a082310000000000000000000000000000000000000000000000000000000082528180612f3c8960048301610395565b03915afa958615613254575b600096613234575b50612f5b6000610dc1565b945b612f7061036e612ee960608b018b612d23565b8610156131a357878691612f9061036e6127bd612ee96060860186612d23565b83101561315d57818380612fa76060840184612d23565b612fb16001610dc1565b612fbb90846118f8565b90612fc5926121ac565b612fce90612d94565b92612ea46130ec9761221f61304f6130d19960008060209b8b6130758361309b9d61308061301c6120cc9f6120cc9f612ea46120cc926130166120cc935b6060810190612d23565b906121ac565b948961305c612ea463eab90da69561221f61304f613044612ea48461301660408a018a612d23565b956040810190612d23565b919092611a2d6001610dc1565b90873b15613150575b6040519a8b998a98899760e01b90565b875260048701612da7565b03925af18015613143575b61311d575b506040810190612d23565b604051938492839182917f70a0823100000000000000000000000000000000000000000000000000000000835260048301610395565b03915afa908115613110575b6000916130f2575b50956124ed565b94612f5d565b61310a915060203d8111612143576121348183610757565b386130e5565b613118612094565b6130dd565b6131369060005b61312e8183610757565b810190610337565b38613090565b503d613124565b61314b612094565b61308b565b613158600080fd5b613065565b8183808992612ea46130ec9761221f61304f6130d19960008060209b8b6130758361309b9d61308061301c6120cc9f6120cc9f612ea46120cc926130166120cc9361300c565b6131e6929550612ea49194506131c16131ec949897612e9a926126da565b966131dc6131d461036e60208401612d19565b891015612de9565b6040810190612d23565b92612d19565b918361322161321b7f9fc8352e52998db4087d5e6e1c1aafa38788e749e5d7a24f5cb230f737954402936114f2565b936114f2565b9361322e611f5760405190565b0390a390565b61324d91965060203d8111612143576121348183610757565b9438612f50565b61325c612094565b612f48565b6132b894509061327c612ec39261327788612d19565b613329565b9081958692613294612ea4612e9a60408d018d612d23565b90836132b26132a36002611f91565b926132ad8d612d19565b6126da565b92613369565b9150612e81565b506132ca6001611540565b6132d76119ae6000610dc1565b11612e7c565b156132e457565b60405162461bcd60e51b815260206004820152601b60248201527f59616b526f757465723a20496e73756666696369656e742066656500000000006044820152606490fd5b9061336461036e92613339600090565b5061335261334a61036e6001611540565b8410156132dd565b612b2561335d6111df565b93846126da565b612717565b92919061337861179d306114f2565b61338182610355565b146133975761339261034a946114f2565b613a67565b506133a461034a936114f2565b6139ff565b156133b057565b60405162461bcd60e51b815260206004820152602860248201527f59616b526f757465723a2050617468206e6565647320746f20626567696e207760448201527f69746820574554480000000000000000000000000000000000000000000000006064820152608490fd5b90612d169291613489613484612ea461347d61344b61343d6040870187612d23565b939060009461221f86610dc1565b613477612aa67f0000000000000000000000000000000000000000000000000000000000000000610355565b146133a9565b8301612d19565b613498565b613492306114f2565b90612e5b565b60006134e46134c96120cc7f00000000000000000000000000000000000000000000000000000000000000006114f2565b63d0e30db0813b1561351b575b604051948593849260e01b90565b825281600481015b03925af1801561350e575b6134fe5750565b61034a90600061312e8183610757565b613516612094565b6134f7565b613523600080fd5b6134d6565b1561352f57565b60405162461bcd60e51b815260206004820152602660248201527f59616b526f757465723a2050617468206e6565647320746f20656e642077697460448201527f68205745544800000000000000000000000000000000000000000000000000006064820152608490fd5b61360e9061034a93926135fe6135cc612ea460408501612ee961221f6127bd6135c3848a612d23565b9390948a612d23565b6135f8612aa67f0000000000000000000000000000000000000000000000000000000000000000610355565b14613528565b33613608306114f2565b92612e5b565b9061362f565b91602061034a929493611ed760408201966000830190610388565b60009061365e6120cc7f00000000000000000000000000000000000000000000000000000000000000006114f2565b6136888363205c2878833b15613693575b6134ec61367b60405190565b9788968795869460e01b90565b845260048401613614565b61369b600080fd5b61366f565b949290979695939160e0860198600087016136ba91610388565b602086016136c791610388565b6040850152606084015260ff16608083015260a082015260c00152565b929561034a96612ea493966137566137618795986137056040880188612d23565b9290966137216120cc6120cc60009c8d9b8c9861221f8a610dc1565b9563d505accf93339861373e87613737306114f2565b9d01612d19565b893b156137a2575b6040519c8d9b8c9a8b9960e01b90565b8952600489016136a0565b03925af18015613795575b613778575b5050612d09565b8161378e92903d1061313c5761312e8183610757565b3880613771565b61379d612094565b61376c565b6137aa600080fd5b613746565b929561034a96612ea493966137566137d08795986137056040880188612d23565b03925af18015613804575b6137e7575b505061359a565b816137fd92903d1061313c5761312e8183610757565b38806137e0565b61380c612094565b6137db565b61034a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95611589565b61034a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95611710565b61034a903361058b565b61034a903390613887613880610dce565b9182611589565b61178c565b61034a919061389d611c0833611be2565b6138ee565b156138a957565b60405162461bcd60e51b815260206004820152601260248201527f4e6f7468696e6720746f207265636f76657200000000000000000000000000006044820152606490fd5b6139036138fb6000610dc1565b835b116138a2565b61391782613910836114f2565b33906139ff565b61394e6139447f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa28926114f2565b926104c160405190565b0390a2565b9061034a9161388c565b61034a9061396d611c0833611be2565b613917600061398461397e82610dc1565b846138fd565b80808080866139956120cc336114f2565b8282156139af575bf1610d7c576139aa612094565b610d7c565b506108fc61399d565b61034a9061395d565b6139da6139d461036e9263ffffffff1690565b60e01b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b613a42600492613a3361034a95613a1963a9059cbb6139c1565b92613a2360405190565b9687946020860190815201613614565b60208201810382520383610757565b613cff565b604090611ed761034a949695939661208a60608401986000850190610388565b90613a4290613a3361034a95600495613a836323b872dd6139c1565b93613a8d60405190565b9788956020870190815201613a47565b15613aa457565b60405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608490fd5b613a42600492613a3361034a95613b3c600084613b2b82610dc1565b8414918215613b49575b5050613a9d565b613a1963095ea7b36139c1565b9091506020613b57896114f2565b63dd62ed3e90613b83613b69306114f2565b92613b8e613b7660405190565b9788958694859460e01b90565b845260048401611f9b565b03915afa918215613bdf575b600092613bb7575b506119ae613baf91610dc1565b148438613b35565b613baf919250613bd76119ae9160203d8111612143576121348183610757565b929150613ba2565b613be7612094565b613b9a565b3d15613c0657613bfb3d610e53565b903d6000602084013e565b606090565b15613c1257565b60405162461bcd60e51b8152806116f1600482016020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b801515610403565b9050519061034a82613c5b565b9061036e9160208183031215613c6357613c88600080fd5b613c63565b15613c9457565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608490fd5b600091613d0c83926114f2565b9082602082019151925af1613d28613d22613bec565b91613c0b565b8051613d376119ae6000610dc1565b11613d3f5750565b613d5b816020613d5061034a945190565b818301019101613c70565b613c8d565b91906040613d81613d6f612476565b92613d7a8496613d86565b8452613d86565b910152565b90602091613d96611a3384610dc1565b92830152565b613da4612476565b5061036e6000820151916122d7602082015191613de2613dca6060604084015193015190565b93613ddb613dd661214a565b978852565b6020870152565b6040850152565b6116239061036e93926115ca565b613e17929161034a91613e0960405190565b948592602084019283613de9565b90810382520383610757565b6060916103919361034a9695613e486040850191613e42835191613d86565b90613df7565b9052613e5d6020840191613e42835191613d86565b9052613e726000830191613e42835191613d86565b90520191612642835190565b613e86612476565b5061036e613e976000830151613f48565b916122d7613ea86020830151613ec4565b91613de2613dca6060613ebe6040850151613ec4565b93015190565b90815191613eda6125a16020946127de86610dc1565b9283613ee66000610dc1565b613efd61036e613ef4865190565b6127de86610dc1565b811015613f4157613f3c906125e8613f32613f2c613f23613f1d88610dc1565b856118dd565b611a2d88610dc1565b87015190565b6125e3838a61251b565b613ee6565b5093505050565b90815191613f5e6125a16020946127de86610dc1565b9283613f6a6000610dc1565b613f7861036e613ef4865190565b811015613f4157613fa5906125e8613f98613f2c613f23613f1d88610dc1565b613fa2838a61251b565b52565b613f6a565b604061036e91613fb8600090565b500151805101519056fea2646970667358221220ab2bc23125a07ec519e2f46f04526991de24c98a06ebde810647d3567008d38364736f6c63430008110033339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab950000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001bb7b44cc398aaa2b76ac6253f0f5634279db9d00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab10000000000000000000000000000000000000000000000000000000000000003000000000000000000000000763b382ba5fbbc697f58b327c2bac05fa1fb51b30000000000000000000000008c0971be6a98dcc61958ffdec4259e5ee833689b0000000000000000000000004548ab9f211d10e511f37f3bcab0fe96e8b04574000000000000000000000000000000000000000000000000000000000000000700000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab10000000000000000000000002f2a2543b76a4166549f7aab2e75bef0aefc5b0f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8000000000000000000000000912ce59144191c1204e64559fe8253a0e49e6548000000000000000000000000fd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da1
Deployed Bytecode
0x6080604052600436101561001e575b361561001c5761001c600080fd5b005b60003560e01c8062b99e361461032957806301ffc9a714610320578063248a9ca3146103175780632f2ff15d1461030e57806331ac99201461030557806336568abe146102fc57806338a3374f146102f357806339b85456146102ea5780633a9a4081146102e157806352a52ab0146102d85780636b453c1f146102cf57806376c7a3c7146102c657806376ebe69c146102bd5780637c7a561b146102b4578063809356aa146102ab57806386e450d1146102a25780638980f11f146102995780638bb9c5bf1461029057806391d148541461028757806392f5d88a1461027e578063952e901214610275578063996d6f701461026c578063a0cf0aea14610263578063a217fddf1461025a578063a3f4df7e14610251578063aede369314610248578063b381cf401461023f578063b9a89ca314610236578063c3accd481461022d578063c8a3a5c614610224578063d547741f1461021b578063d73792a914610212578063d8baf7cf14610209578063dd8544b314610200578063dede7f15146101f7578063f2fde38b146101ee578063f6ee13a6146101e5578063f8742254146101dc5763faa3f2f90361000e576101d76113f2565b61000e565b506101d76113aa565b506101d7611379565b506101d76112ca565b506101d761129f565b506101d7611243565b506101d761121c565b506101d76111f2565b506101d76111b7565b506101d7611190565b506101d7611169565b506101d761112f565b506101d7610f6b565b506101d7610f44565b506101d7610f0e565b506101d7610de0565b506101d7610d97565b506101d7610d41565b506101d7610d17565b506101d7610cd1565b506101d7610b96565b506101d7610b6f565b506101d7610b47565b506101d7610aee565b506101d7610ac0565b506101d7610a4b565b506101d7610a20565b506101d76109f6565b506101d76109ad565b506101d7610966565b506101d76108a9565b506101d76106d1565b506101d7610612565b506101d7610576565b506101d761054f565b506101d7610522565b506101d76104a0565b506101d7610434565b506101d76103a5565b600080fd5b600091031261034257565b61034a600080fd5b565b61036e916008021c5b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b9061036e915461034c565b61036e60006002610371565b61039190610355565b9052565b60208101929161034a9190610388565b50346103d2575b6103b7366004610337565b6103ce6103c261037c565b60405191829182610395565b0390f35b6103da600080fd5b6103ac565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b0361033257565b9050359061034a826103df565b9061036e916020818303121561040a5761042f600080fd5b61040a565b5034610463575b6103ce61045161044c366004610417565b61141a565b60405191829182901515815260200190565b61046b600080fd5b61043b565b80610403565b9050359061034a82610470565b9061036e91602081830312156104765761049b600080fd5b610476565b50346104ce575b6103ce6104bd6104b8366004610483565b61154a565b6040515b9182918290815260200190565b6104d6600080fd5b6104a7565b61040381610355565b9050359061034a826104db565b919061036e90604084820312610515575b61050c8185610476565b936020016104e4565b61051d600080fd5b610502565b5034610542575b61053d6105373660046104f1565b90611589565b604051005b61054a600080fd5b610529565b5034610569575b61053d610564366004610483565b611f6a565b610571600080fd5b610556565b5034610591575b61053d61058b3660046104f1565b9061178c565b610599600080fd5b61057d565b908160809103126105ac5790565b61036e600080fd5b9091606082840312610605575b61036e6105e184843567ffffffffffffffff81116105f8575b850161059e565b936105ef8160208601610476565b936040016104e4565b610600600080fd5b6105da565b61060d600080fd5b6105c1565b5061053d6106213660046105b4565b9161341b565b60ff8116610403565b9050359061034a82610627565b60e0818303126106c4575b61066582823567ffffffffffffffff81116106b7575b830161059e565b926106738360208401610476565b9261068181604085016104e4565b9261068f8260608301610476565b9261036e6106a08460808501610630565b936106ae8160a08601610476565b9360c001610476565b6106bf600080fd5b61065e565b6106cc600080fd5b610648565b50346106f2575b61053d6106e636600461063d565b959490949391936137af565b6106fa600080fd5b6106d8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810190811067ffffffffffffffff82111761079757604052565b61079f610727565b604052565b9061034a6107b160405190565b9283610757565b6020809167ffffffffffffffff81116107d057020190565b6107d8610727565b020190565b909291926107f26107ed826107b8565b6107a4565b9381855260208086019202830192818411610830575b915b8383106108175750505050565b6020809161082584866104e4565b81520192019161080a565b610838600080fd5b610808565b9061036e9181601f82011215610859575b6020813591016107dd565b610861600080fd5b61084e565b9061036e9160208183031261089c575b80359067ffffffffffffffff821161088f575b0161083d565b610897600080fd5b610889565b6108a4600080fd5b610876565b50346108c3575b61053d6108be366004610866565b611ea6565b6108cb600080fd5b6108b0565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b61092060019161090e815490565b84101561092957600052602060002090565b91020190600090565b6109316108d0565b600052602060002090565b60036000610948825490565b831015610963575061036e9161095d91610900565b90610371565b80fd5b5034610983575b6103ce6103c261097e366004610483565b61093c565b61098b600080fd5b61096d565b9061036e91602081830312156104e4576109a8600080fd5b6104e4565b50346109c7575b61053d6109c2366004610990565b613811565b6109cf600080fd5b6109b4565b61036e916008021c81565b9061036e91546109d4565b61036e600060016109df565b5034610a13575b610a08366004610337565b6103ce6104bd6109ea565b610a1b600080fd5b6109fd565b5034610a3e575b610a32366004610337565b6103ce6104bd60035490565b610a46600080fd5b610a27565b5034610a69575b610a5d366004610337565b6103ce6104bd60045490565b610a71600080fd5b610a52565b608081830312610ab3575b610a8b8282610476565b9261036e610a9c84602085016104e4565b93610aaa81604086016104e4565b93606001610630565b610abb600080fd5b610a81565b5034610ae1575b6103ce6104bd610ad8366004610a76565b929190916120a1565b610ae9600080fd5b610ac7565b5034610b09575b61053d610b033660046105b4565b91612d09565b610b11600080fd5b610af5565b919061036e90604084820312610b3a575b610b3181856104e4565b93602001610476565b610b42600080fd5b610b27565b5034610b62575b61053d610b5c366004610b16565b90613953565b610b6a600080fd5b610b4e565b5034610b89575b61053d610b84366004610483565b613865565b610b91600080fd5b610b76565b5034610bb4575b6103ce610451610bae3660046104f1565b9061151a565b610bbc600080fd5b610b9d565b909182601f83011215610c00575b602082359267ffffffffffffffff8411610bf3575b01926020830284011161034257565b610bfb600080fd5b610be4565b610c08600080fd5b610bcf565b608081830312610c6f575b610c228282610476565b92610c5e610c3384602085016104e4565b93610c4181604086016104e4565b9360608101359067ffffffffffffffff8211610c62575b01610bc1565b9091565b610c6a600080fd5b610c58565b610c77600080fd5b610c18565b9060608061034a93610c9660008201516000860190610388565b610ca860208201516020860190610388565b610cba60408201516040860190610388565b0151910152565b60808101929161034a9190610c7c565b5034610cfe575b6103ce610cf2610ce9366004610c0d565b939290926121d8565b60405191829182610cc1565b610d06600080fd5b610cd8565b60046000610948825490565b5034610d34575b6103ce6103c2610d2f366004610483565b610d0b565b610d3c600080fd5b610d1e565b5034610d62575b61053d610d5636600461063d565b959490949391936136e4565b610d6a600080fd5b610d48565b61035561036e61036e9290565b61036e90610d6f565b61036e6000610d7c565b61036e610d85565b5034610db4575b610da9366004610337565b6103ce6103c2610d8f565b610dbc600080fd5b610d9e565b61036e61036e61036e9290565b61036e6000610dc1565b61036e610dce565b5034610dfd575b610df2366004610337565b6103ce6104bd610dd8565b610e05600080fd5b610de7565b610e4760209167ffffffffffffffff8111610e4b57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690565b0190565b6106ff610727565b90610e606107ed83610e0a565b918252565b610e6f6010610e53565b7f43616d656c6f7459616b526f7574657200000000000000000000000000000000602082015290565b61036e610e65565b61036e610e98565b61036e610ea0565b60005b838110610ec35750506000910152565b8181015183820152602001610eb3565b610ef46106ff602093610e4793610ee8815190565b80835293849260200190565b95869101610eb0565b602080825261036e92910190610ed3565b5034610f37575b610f20366004610337565b6103ce610f2b610ea8565b60405191829182610efd565b610f3f600080fd5b610f15565b5034610f5e575b61053d610f59366004610483565b6139b8565b610f66600080fd5b610f4b565b5034610fa6575b610f7d366004610337565b6103ce7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16103c2565b610fae600080fd5b610f72565b919060a083820312611020575b610fca8184610476565b92610fd882602083016104e4565b9261036e610fe984604085016104e4565b9361100a81606086013567ffffffffffffffff8111611013575b860161083d565b93608001610476565b61101b600080fd5b611003565b611028600080fd5b610fc0565b9061104d61104661103c845190565b8084529260200190565b9260200190565b9060005b81811061105e5750505090565b90919261107b6110746001928651815260200190565b9460200190565b929101611051565b90610e4781602093610388565b9061109f61104661103c845190565b9060005b8181106110b05750505090565b9091926110c36110746001928651611083565b9291016110a3565b9061036e906060806111166111046110f2608086016000890151878203600089015261102d565b60208801518682036020880152611090565b60408701518582036040870152611090565b940151910152565b602080825261036e929101906110cb565b503461115c575b6103ce611150611147366004610fb3565b939290926127e4565b6040519182918261111e565b611164600080fd5b611136565b5034611183575b61053d61117e366004610990565b612040565b61118b600080fd5b611170565b50346111aa575b61053d6111a5366004610866565b611e4a565b6111b2600080fd5b611197565b50346111d2575b61053d6111cc3660046104f1565b90611710565b6111da600080fd5b6111be565b61036e612710610dc1565b61036e6111df565b503461120f575b611204366004610337565b6103ce6104bd6111ea565b611217600080fd5b6111f9565b5034611236575b61053d611231366004610990565b61383b565b61123e600080fd5b611223565b503461125d575b61053d611258366004610990565b611c42565b611265600080fd5b61124a565b9091606082840312611292575b61036e6112848484610476565b936105ef81602086016104e4565b61129a600080fd5b611277565b50346112bd575b6103ce610cf26112b736600461126a565b91612327565b6112c5600080fd5b6112a6565b50346112e4575b61053d6112df366004610990565b61386f565b6112ec600080fd5b6112d1565b909160c08284031261136c575b6113088383610476565b9261131681602085016104e4565b9261132482604083016104e4565b9261036e61134884606085013567ffffffffffffffff811161135f575b850161083d565b936113568160808601610476565b9360a001610476565b611367600080fd5b611341565b611374600080fd5b6112fe565b503461139d575b6103ce6111506113913660046112f1565b94939093929192612532565b6113a5600080fd5b611380565b50346113e5575b6113bc366004610337565b6103ce7f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab956104bd565b6113ed600080fd5b6113b1565b503461140d575b61053d6114073660046105b4565b9161359a565b611415600080fd5b6113f9565b7f7965db0b000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082161490811561146a575090565b61036e91507fffffffff00000000000000000000000000000000000000000000000000000000167f01ffc9a7000000000000000000000000000000000000000000000000000000001490565b905b600052602052604060002090565b61035561036e61036e9273ffffffffffffffffffffffffffffffffffffffff1690565b61036e906114c6565b61036e906114e9565b906114b8906114f2565b61036e905b60ff1690565b61036e9054611505565b61036e916115349161152e600091826114b6565b016114fb565b611510565b61036e9081565b61036e9054611539565b600161156361036e9261155b600090565b5060006114b6565b01611540565b9061034a9161157f61157a8261154a565b611593565b9061034a916117e0565b9061034a91611569565b61034a903390611652565b61036e61036e61036e9273ffffffffffffffffffffffffffffffffffffffff1690565b61036e90610dc1565b610e476115e2926020926115dc815190565b94859290565b93849101610eb0565b61162961036e9392611623611623937f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260170190565b906115ca565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000815260110190565b90611664611660828461151a565b1590565b61166c575050565b6116f19161036e6116a561169f6116856116d9956114e9565b61169961169360149261159e565b91610dc1565b90611a07565b926115c1565b6116b460209161169983610dc1565b926116cd6116c160405190565b948593840192836115eb565b90810382520382610757565b60405191829162461bcd60e51b835260048301610efd565b0390fd5b9061034a9161170661157a8261154a565b9061034a91611856565b9061034a916116f5565b1561172157565b60405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608490fd5b61034a91906117b16117a233610355565b610355565b6117ab84610355565b1461171a565b611856565b9060ff905b9181191691161790565b906117d561036e6117dc92151590565b82546117b6565b9055565b906117ee611660828461151a565b6117f6575050565b611810600161180b83600061152e87826114b6565b6117c5565b33906118466118406118407f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9590565b926114f2565b9261185060405190565b600090a4565b90611861818361151a565b611869575050565b61187d600061180b838261152e87826114b6565b33906118466118406118407ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9590565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818102929181159184041417156118f057565b61034a6118ad565b919082018092116118f057565b369037565b9061034a61192061191a84610e53565b93610e0a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00160208401611905565b906001602091611959845190565b811015611967575b02010190565b61196f6108d0565b611961565b6001908015611981570390565b6119896118ad565b0390565b61150a61036e61036e9290565b61036e906119b26119ae61036e9460ff1690565b9190565b901c90565b156119be57565b60405162461bcd60e51b8152806116f1600482016020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b9190600290611a38611a33611a2483611a1f86610dc1565b6118dd565b611a2d85610dc1565b906118f8565b61190a565b916000916030611a50611a4a85610dc1565b8661194b565b53611aa4611a9b7f780000000000000000000000000000000000000000000000000000000000000092611a1f6001958695881a611a95611a8f88610dc1565b8b61194b565b53610dc1565b611a2d83610dc1565b915b611ac7575b505061036e9293611ac16119ae61036e93610dc1565b146119b7565b9094611ad282610dc1565b861115611b5e57611b4b611b458392611b28611b0b7f303132333435363738396162636465660000000000000000000000000000000090565b611b15600f610dc1565b83166010811015611b51575b1a60f81b90565b861a611b348a8961194b565b53611b3f600461198d565b9061199a565b96611974565b91611aa6565b611b596108d0565b611b21565b94611aab565b15611b6b57565b60405162461bcd60e51b815260206004820152602860248201527f4d61696e7461696e61626c653a2043616c6c6572206973206e6f742061206d6160448201527f696e7461696e65720000000000000000000000000000000000000000000000006064820152608490fd5b61034a90611c0d611c08335b7f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab9561151a565b611b64565b61034a90611c1a816114f2565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91613b0f565b61034a90611bd6565b61034a90611c5b611c0833611be2565b611e07565b90611c6f61104661103c845190565b9060005b818110611c805750505090565b909192611c936110746001928651611083565b929101611c73565b602080825261036e92910190611c60565b919060086117bb910291611cdf7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841b90565b921b90565b9190611cf561036e6117dc93610dc1565b908354611cac565b61034a91600091611ce4565b818110611d14575050565b80611d226000600193611cfd565b01611d09565b9091828110611d3657505050565b61034a9290611d4c905b92600052602060002090565b9081019101611d09565b9061034a91680100000000000000008211611d77575b805490828155611d28565b611d7f610727565b611d6c565b61036e9051610355565b6001611dbf611d40611d9e855190565b9467ffffffffffffffff8611611df0575b611db98686611d56565b60200190565b92049160005b838110611dd25750505050565b6001906020611de361036e86611d84565b9401938184015501611dc5565b611df8610727565b611daf565b9061034a91611d8e565b61034a907f658ff1688002926d8f426cb10c052ec29003f50042df9652d8613484c1a58647611e3560405190565b80611e408482611c9b565b0390a16003611dfd565b61034a90611c4b565b61034a90611e63611c0833611be2565b61034a907febf7325f48e05e5e38809c69f8b02a7c907ed31d8768e6c2d841b1296a9225fe611e9160405190565b80611e9c8482611c9b565b0390a16004611dfd565b61034a90611e53565b61034a90611ebf611c0833611be2565b611f1a565b90815260408101929161034a9160200152565b0152565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff906117bb565b90611f1361036e6117dc92610dc1565b8254611edb565b61034a90611f286001611540565b817f4bb8a6184424e4bb853a4836042f5a726e4e710873989bfc6abdab19966f5b7091611f60611f5760405190565b92839283611ec4565b0390a16001611f03565b61034a90611eaf565b61034a90611f83611c0833611be2565b611ff0565b61036e90610355565b61036e9054611f88565b91602061034a929493611fb660408201966000830190610388565b0190610388565b9073ffffffffffffffffffffffffffffffffffffffff906117bb565b90611fe961036e6117dc926114f2565b8254611fbd565b61034a90611ffe6002611f91565b817fb2c853ac4d80d18d058c43d8018d077a036e542a79acae1647f5ad2a8c76f4e29161203661202d60405190565b92839283611f9b565b0390a16002611fd9565b61034a90611f73565b9050519061034a82610470565b9061036e91602081830312156120495761206e600080fd5b612049565b90815260608101939261034a929091604091611fb6905b6020830190610388565b506040513d6000823e3d90fd5b919260209194936120ee6120b3600090565b966120f76120d16120cc6120cc61095d60049889610900565b6114f2565b9363ef99893a926120e160405190565b9889978896879660e01b90565b86528501612073565b03915afa6000918161211a575b506121165750905061036e6000610dc1565b9150565b61213c91925060203d8111612143575b6121348183610757565b810190612056565b9038612104565b503d61212a565b61036e60806107a4565b61215c61214a565b906000825260208080808501600081520160005b8152016000905250565b61036e612154565b60019060ff1660ff8114612194570190565b610e476118ad565b61036e61036e61036e9260ff1690565b916020918110156121bc57020190565b6107d86108d0565b3561036e81610627565b9061039190610355565b9094939192946121e661217a565b506121ef61217a565b9360005b846121fd8261219c565b101561231d57600484602061223061095d61222a6122258e8c61221f8a61219c565b916121ac565b6121c4565b85610900565b9261223d6120cc856114f2565b6120ee63ef99893a612253898b6120e160405190565b03915afa600091816122fd575b50612276575050612271905b612182565b6121f3565b6000916122828361198d565b60ff85161480156122e7575b61229f575b50505061227190612182565b612271939850906122bd6122de926122b561214a565b9485016121ce565b6122ca86602085016121ce565b6122d785604085016121ce565b6060830152565b95903880612293565b506122f661036e60608b015190565b821161228e565b61231691925060203d8111612143576121348183610757565b9038612260565b5093955050505050565b909161233161217a565b5061233a61217a565b9160005b600461234b61036e825490565b6123548361219c565b101561244d5782602061236a61095d8585610900565b926123776120cc856114f2565b6120ee63ef99893a61238d8a8d6120e160405190565b03915afa6000918161242d575b506123b55750506123b090600161226c57612182565b61233e565b6000916123c18361198d565b60ff8516148015612417575b6123de575b5050506123b090612182565b6123b0939650906123f461240e926122b561214a565b61240188602085016121ce565b6122d786604085016121ce565b939038806123d2565b5061242661036e606089015190565b82116123cd565b61244691925060203d8111612143576121348183610757565b903861239a565b50505050905090565b61245e61214a565b90606082526020808080850160608152016060612170565b61036e612456565b1561248557565b60405162461bcd60e51b815260206004820152601c60248201527f59616b526f757465723a20496e76616c6964206d61782d7374657073000000006044820152606490fd5b90610e606107ed836107b8565b9061034a6119206124e7846124ca565b936107b8565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612194570190565b9060208091611959845190565b61036e6000610e53565b929195909461253f612476565b5060009061254c82610dc1565b8611806126c3575b61255d9061247e565b6125678786613d60565b908861257284610dc1565b600092908111156126b257612587925061272d565b905b6003966125a66125a161259a8a5490565b8851611a2d565b6124d7565b996125b085610dc1565b8b6125bc61036e8c5490565b8210156125f257906125e86125ed926125e3836125dd8f8261095d91610900565b9261251b565b6121ce565b6124ed565b6125b0565b5050909192939495969861260586610dc1565b61261061036e8a5190565b81101561265257806125e88b6125e38f612647858f61263d61263861264d9a6126429361251b565b611d84565b955490565b6118f8565b9061251b565b612605565b5090919395999294975061266a965061036e9861290f565b9061267760208301515190565b6126836119ae83610dc1565b1461268f575b50613e7e565b61269d908201610391612528565b6126ac60408201610391612528565b38612689565b50506126bd90610dc1565b90612589565b5061255d6126d16005610dc1565b87109050612554565b919082039182116118f057565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8115612721570490565b6127296126e7565b0490565b90919061277c60009360606002917f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1612776612770670de0b6b3a7640000610dc1565b94610dc1565b936127e4565b604081015151906000916127926119ae84610dc1565b0361279c57505050565b61036e9394506127cd6127d19392611a1f92016126476127bd825192515190565b6127c76001610dc1565b906126da565b5190565b6127de633b9aca00610dc1565b90612717565b949290926127f0612476565b506000936127fd85610dc1565b8611806128f8575b61280e9061247e565b6128188188613d60565b946003976128316125a161282a8b5490565b8751611a2d565b9661283b83610dc1565b8a61284761036e825490565b82101561287157906125e861286261095d8361286c95610900565b6125e3838d61251b565b61283b565b50509091929394959761288384610dc1565b61288e61036e895190565b8110156128c557806125e88c6125e36128ba846126426128b58f6128c0996126389161251b565b945490565b8d61251b565b612883565b50919396909295506128e894985061036e976128e087610dc1565b97889561290f565b9161268361036e60208501515190565b5061280e6129066005610dc1565b87109050612805565b9192909395949561291e612476565b5061292887613d9c565b918297612933600090565b94859060009061294282610dc1565b8b1415966129518a8c84612327565b90606082019161295f835190565b61296b6119ae87610dc1565b03612c55575b5050506001996129808b610dc1565b871180612c1b575b61299c575b50505050505050505050505090565b9082916129aa8c9594610dc1565b945b6129b7575b5061298d565b6129c261036e885190565b851015612c1657846129db61179d6126388e988b61251b565b6129e483610355565b14612c08578d8a8a8a612a046129fd612638878461251b565b8789612327565b9960608b019a612a128c5190565b612a1e6119ae8c610dc1565b14612bf457612a2c8d613d9c565b94612b5e575b8b6127cd8c8c612a7e9a9b9c9d9e9f94612a646040612a5d612a55612a6b995190565b948401611d84565b9201611d84565b918a613e23565b612a78612638898561251b565b9061290f565b612a8781613faa565b8c612aac612aa6612aa085805160409091015151015190565b93610355565b91610355565b1480612b55575b612acd575b5050612ac3906124ed565b939291908b6129ac565b919e909a8e60608d01612ade815190565b906060850191612af26119ae61036e855190565b11612b0a575b5050505050612ac390999d9038612ab8565b91612b256127d1926127c7612b20612b2b965190565b915190565b906118dd565b612b3b6119ae61036e84876126da565b11612b48578e8180612af8565b9a509d612ac391506124ed565b508b8111612ab3565b899b8a9b506127cd82612b9f6020612b87612a7e9c9d9e9f6120cc6120cc91612a6b9901611d84565b6369cff80d90612b9660405190565b93849260e01b90565b825260049082905afa908115612be7575b600091612bc9575b509d509250509b9998979650612a32565b612be1915060203d8111612143576121348183610757565b38612bb8565b612bef612094565b612bb0565b505050505050612ac39192939495506124ed565b612ac39192939495506124ed565b6129b1565b50612c35612c2b60208701515190565b6127de6020610dc1565b612c4e6119ae61036e612c486002610dc1565b8b6126da565b1115612988565b909192995088612c98575b8483926127cd92612c72612c8f965190565b612c896040612c828a8501611d84565b9301611d84565b92613e23565b96388080612971565b612c8f9291945080612cb96020612b876120cc6120cc896127cd9701611d84565b825260049082905afa908115612cfc575b600091612cde575b50959293509050612c60565b612cf6915060203d8111612143576121348183610757565b38612cd2565b612d04612094565b612cca565b90612d1692913390612e5b565b50565b3561036e81610470565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe13682900301821215612d87575b01602081359167ffffffffffffffff8311612d7a575b0191602082023603831361034257565b612d82600080fd5b612d6a565b612d8f600080fd5b612d54565b3561036e816104db565b61039190610dc1565b9095949261034a94612ddf611fb692612dd5608096612dcb60a088019c6000890152565b6020870190612d9e565b6040850190610388565b6060830190610388565b15612df057565b60405162461bcd60e51b815260206004820152602560248201527f59616b526f757465723a20496e73756666696369656e74206f7574707574206160448201527f6d6f756e740000000000000000000000000000000000000000000000000000006064820152608490fd5b93849391612e6885612d19565b93612e736000610dc1565b811180156132bf575b613261575b5083612ec391612ea9612ea4612e9a60408b018b612d23565b61221f6000610dc1565b612d94565b90612ebd612ea4612e9a60608c018c612d23565b91613369565b612eee612ea4612ed66040880188612d23565b61221f6127bd612ee960408c018c612d23565b905090565b93612efb6120cc866114f2565b946020612f0760405190565b9687907f70a082310000000000000000000000000000000000000000000000000000000082528180612f3c8960048301610395565b03915afa958615613254575b600096613234575b50612f5b6000610dc1565b945b612f7061036e612ee960608b018b612d23565b8610156131a357878691612f9061036e6127bd612ee96060860186612d23565b83101561315d57818380612fa76060840184612d23565b612fb16001610dc1565b612fbb90846118f8565b90612fc5926121ac565b612fce90612d94565b92612ea46130ec9761221f61304f6130d19960008060209b8b6130758361309b9d61308061301c6120cc9f6120cc9f612ea46120cc926130166120cc935b6060810190612d23565b906121ac565b948961305c612ea463eab90da69561221f61304f613044612ea48461301660408a018a612d23565b956040810190612d23565b919092611a2d6001610dc1565b90873b15613150575b6040519a8b998a98899760e01b90565b875260048701612da7565b03925af18015613143575b61311d575b506040810190612d23565b604051938492839182917f70a0823100000000000000000000000000000000000000000000000000000000835260048301610395565b03915afa908115613110575b6000916130f2575b50956124ed565b94612f5d565b61310a915060203d8111612143576121348183610757565b386130e5565b613118612094565b6130dd565b6131369060005b61312e8183610757565b810190610337565b38613090565b503d613124565b61314b612094565b61308b565b613158600080fd5b613065565b8183808992612ea46130ec9761221f61304f6130d19960008060209b8b6130758361309b9d61308061301c6120cc9f6120cc9f612ea46120cc926130166120cc9361300c565b6131e6929550612ea49194506131c16131ec949897612e9a926126da565b966131dc6131d461036e60208401612d19565b891015612de9565b6040810190612d23565b92612d19565b918361322161321b7f9fc8352e52998db4087d5e6e1c1aafa38788e749e5d7a24f5cb230f737954402936114f2565b936114f2565b9361322e611f5760405190565b0390a390565b61324d91965060203d8111612143576121348183610757565b9438612f50565b61325c612094565b612f48565b6132b894509061327c612ec39261327788612d19565b613329565b9081958692613294612ea4612e9a60408d018d612d23565b90836132b26132a36002611f91565b926132ad8d612d19565b6126da565b92613369565b9150612e81565b506132ca6001611540565b6132d76119ae6000610dc1565b11612e7c565b156132e457565b60405162461bcd60e51b815260206004820152601b60248201527f59616b526f757465723a20496e73756666696369656e742066656500000000006044820152606490fd5b9061336461036e92613339600090565b5061335261334a61036e6001611540565b8410156132dd565b612b2561335d6111df565b93846126da565b612717565b92919061337861179d306114f2565b61338182610355565b146133975761339261034a946114f2565b613a67565b506133a461034a936114f2565b6139ff565b156133b057565b60405162461bcd60e51b815260206004820152602860248201527f59616b526f757465723a2050617468206e6565647320746f20626567696e207760448201527f69746820574554480000000000000000000000000000000000000000000000006064820152608490fd5b90612d169291613489613484612ea461347d61344b61343d6040870187612d23565b939060009461221f86610dc1565b613477612aa67f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1610355565b146133a9565b8301612d19565b613498565b613492306114f2565b90612e5b565b60006134e46134c96120cc7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16114f2565b63d0e30db0813b1561351b575b604051948593849260e01b90565b825281600481015b03925af1801561350e575b6134fe5750565b61034a90600061312e8183610757565b613516612094565b6134f7565b613523600080fd5b6134d6565b1561352f57565b60405162461bcd60e51b815260206004820152602660248201527f59616b526f757465723a2050617468206e6565647320746f20656e642077697460448201527f68205745544800000000000000000000000000000000000000000000000000006064820152608490fd5b61360e9061034a93926135fe6135cc612ea460408501612ee961221f6127bd6135c3848a612d23565b9390948a612d23565b6135f8612aa67f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1610355565b14613528565b33613608306114f2565b92612e5b565b9061362f565b91602061034a929493611ed760408201966000830190610388565b60009061365e6120cc7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16114f2565b6136888363205c2878833b15613693575b6134ec61367b60405190565b9788968795869460e01b90565b845260048401613614565b61369b600080fd5b61366f565b949290979695939160e0860198600087016136ba91610388565b602086016136c791610388565b6040850152606084015260ff16608083015260a082015260c00152565b929561034a96612ea493966137566137618795986137056040880188612d23565b9290966137216120cc6120cc60009c8d9b8c9861221f8a610dc1565b9563d505accf93339861373e87613737306114f2565b9d01612d19565b893b156137a2575b6040519c8d9b8c9a8b9960e01b90565b8952600489016136a0565b03925af18015613795575b613778575b5050612d09565b8161378e92903d1061313c5761312e8183610757565b3880613771565b61379d612094565b61376c565b6137aa600080fd5b613746565b929561034a96612ea493966137566137d08795986137056040880188612d23565b03925af18015613804575b6137e7575b505061359a565b816137fd92903d1061313c5761312e8183610757565b38806137e0565b61380c612094565b6137db565b61034a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95611589565b61034a907f339759585899103d2ace64958e37e18ccb0504652c81d4a1b8aa80fe2126ab95611710565b61034a903361058b565b61034a903390613887613880610dce565b9182611589565b61178c565b61034a919061389d611c0833611be2565b6138ee565b156138a957565b60405162461bcd60e51b815260206004820152601260248201527f4e6f7468696e6720746f207265636f76657200000000000000000000000000006044820152606490fd5b6139036138fb6000610dc1565b835b116138a2565b61391782613910836114f2565b33906139ff565b61394e6139447f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa28926114f2565b926104c160405190565b0390a2565b9061034a9161388c565b61034a9061396d611c0833611be2565b613917600061398461397e82610dc1565b846138fd565b80808080866139956120cc336114f2565b8282156139af575bf1610d7c576139aa612094565b610d7c565b506108fc61399d565b61034a9061395d565b6139da6139d461036e9263ffffffff1690565b60e01b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b613a42600492613a3361034a95613a1963a9059cbb6139c1565b92613a2360405190565b9687946020860190815201613614565b60208201810382520383610757565b613cff565b604090611ed761034a949695939661208a60608401986000850190610388565b90613a4290613a3361034a95600495613a836323b872dd6139c1565b93613a8d60405190565b9788956020870190815201613a47565b15613aa457565b60405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608490fd5b613a42600492613a3361034a95613b3c600084613b2b82610dc1565b8414918215613b49575b5050613a9d565b613a1963095ea7b36139c1565b9091506020613b57896114f2565b63dd62ed3e90613b83613b69306114f2565b92613b8e613b7660405190565b9788958694859460e01b90565b845260048401611f9b565b03915afa918215613bdf575b600092613bb7575b506119ae613baf91610dc1565b148438613b35565b613baf919250613bd76119ae9160203d8111612143576121348183610757565b929150613ba2565b613be7612094565b613b9a565b3d15613c0657613bfb3d610e53565b903d6000602084013e565b606090565b15613c1257565b60405162461bcd60e51b8152806116f1600482016020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b801515610403565b9050519061034a82613c5b565b9061036e9160208183031215613c6357613c88600080fd5b613c63565b15613c9457565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608490fd5b600091613d0c83926114f2565b9082602082019151925af1613d28613d22613bec565b91613c0b565b8051613d376119ae6000610dc1565b11613d3f5750565b613d5b816020613d5061034a945190565b818301019101613c70565b613c8d565b91906040613d81613d6f612476565b92613d7a8496613d86565b8452613d86565b910152565b90602091613d96611a3384610dc1565b92830152565b613da4612476565b5061036e6000820151916122d7602082015191613de2613dca6060604084015193015190565b93613ddb613dd661214a565b978852565b6020870152565b6040850152565b6116239061036e93926115ca565b613e17929161034a91613e0960405190565b948592602084019283613de9565b90810382520383610757565b6060916103919361034a9695613e486040850191613e42835191613d86565b90613df7565b9052613e5d6020840191613e42835191613d86565b9052613e726000830191613e42835191613d86565b90520191612642835190565b613e86612476565b5061036e613e976000830151613f48565b916122d7613ea86020830151613ec4565b91613de2613dca6060613ebe6040850151613ec4565b93015190565b90815191613eda6125a16020946127de86610dc1565b9283613ee66000610dc1565b613efd61036e613ef4865190565b6127de86610dc1565b811015613f4157613f3c906125e8613f32613f2c613f23613f1d88610dc1565b856118dd565b611a2d88610dc1565b87015190565b6125e3838a61251b565b613ee6565b5093505050565b90815191613f5e6125a16020946127de86610dc1565b9283613f6a6000610dc1565b613f7861036e613ef4865190565b811015613f4157613fa5906125e8613f98613f2c613f23613f1d88610dc1565b613fa2838a61251b565b52565b613f6a565b604061036e91613fb8600090565b500151805101519056fea2646970667358221220ab2bc23125a07ec519e2f46f04526991de24c98a06ebde810647d3567008d38364736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001bb7b44cc398aaa2b76ac6253f0f5634279db9d00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab10000000000000000000000000000000000000000000000000000000000000003000000000000000000000000763b382ba5fbbc697f58b327c2bac05fa1fb51b30000000000000000000000008c0971be6a98dcc61958ffdec4259e5ee833689b0000000000000000000000004548ab9f211d10e511f37f3bcab0fe96e8b04574000000000000000000000000000000000000000000000000000000000000000700000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab10000000000000000000000002f2a2543b76a4166549f7aab2e75bef0aefc5b0f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8000000000000000000000000912ce59144191c1204e64559fe8253a0e49e6548000000000000000000000000fd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da1
-----Decoded View---------------
Arg [0] : _adapters (address[]): 0x763b382BA5FBBC697F58B327C2baC05fA1fB51B3,0x8C0971be6a98DcC61958fFDEc4259e5ee833689b,0x4548ab9F211D10e511F37F3bcAB0FE96E8B04574
Arg [1] : _trustedTokens (address[]): 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1,0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f,0xaf88d065e77c8cC2239327C5EDb3A432268e5831,0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8,0x912CE59144191C1204E64559FE8253a0e49E6548,0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9,0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1
Arg [2] : _feeClaimer (address): 0x01Bb7B44cc398AaA2b76Ac6253F0F5634279Db9D
Arg [3] : _wrapped_native (address): 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1
-----Encoded View---------------
16 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [2] : 00000000000000000000000001bb7b44cc398aaa2b76ac6253f0f5634279db9d
Arg [3] : 00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [5] : 000000000000000000000000763b382ba5fbbc697f58b327c2bac05fa1fb51b3
Arg [6] : 0000000000000000000000008c0971be6a98dcc61958ffdec4259e5ee833689b
Arg [7] : 0000000000000000000000004548ab9f211d10e511f37f3bcab0fe96e8b04574
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [9] : 00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Arg [10] : 0000000000000000000000002f2a2543b76a4166549f7aab2e75bef0aefc5b0f
Arg [11] : 000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831
Arg [12] : 000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8
Arg [13] : 000000000000000000000000912ce59144191c1204e64559fe8253a0e49e6548
Arg [14] : 000000000000000000000000fd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9
Arg [15] : 000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da1
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$77.74
Net Worth in ETH
0.027165
Token Allocations
EZETH
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ARB | 100.00% | $3,061.15 | 0.0254 | $77.74 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.