Source Code
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| - | 12472300 | 1763 days ago | 8.27823773 ETH | ||||
| - | 12472300 | 1763 days ago | 8.27079401 ETH | ||||
| - | 12472300 | 1763 days ago | 0.00744371 ETH | ||||
| - | 12472288 | 1763 days ago | 0.00744371 ETH | ||||
| - | 12472283 | 1763 days ago | 35.51549279 ETH | ||||
| - | 12472283 | 1763 days ago | 35.48355759 ETH | ||||
| - | 12472283 | 1763 days ago | 0.0319352 ETH | ||||
| - | 12472253 | 1763 days ago | 717.10634694 ETH | ||||
| - | 12472253 | 1763 days ago | 716.46153156 ETH | ||||
| - | 12472253 | 1763 days ago | 0.64481537 ETH | ||||
| - | 12472249 | 1763 days ago | 1,590.50468046 ETH | ||||
| - | 12472249 | 1763 days ago | 1,589.0745134 ETH | ||||
| - | 12472249 | 1763 days ago | 1.43016706 ETH | ||||
| - | 12472247 | 1763 days ago | 1.42510489 ETH | ||||
| - | 12472243 | 1763 days ago | 1.42510489 ETH | ||||
| - | 12471830 | 1763 days ago | 681.04448291 ETH | ||||
| - | 12471830 | 1763 days ago | 681.04448291 ETH | ||||
| - | 12471818 | 1763 days ago | 1,531.348724 ETH | ||||
| - | 12471818 | 1763 days ago | 1,531.348724 ETH | ||||
| - | 12471425 | 1763 days ago | 1,101.10245224 ETH | ||||
| - | 12471425 | 1763 days ago | 1,101.10245224 ETH | ||||
| - | 12471397 | 1763 days ago | 15.48447385 ETH | ||||
| - | 12471397 | 1763 days ago | 15.48447385 ETH | ||||
| - | 12470852 | 1763 days ago | 2.0018 ETH | ||||
| - | 12470852 | 1763 days ago | 2 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AaveSaverReceiverOV2
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2021-04-29
*/
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
interface ERC20 {
function totalSupply() external view returns (uint256 supply);
function balanceOf(address _owner) external view returns (uint256 balance);
function transfer(address _to, uint256 _value) external returns (bool success);
function transferFrom(address _from, address _to, uint256 _value)
external
returns (bool success);
function approve(address _spender, uint256 _value) external returns (bool success);
function allowance(address _owner, address _spender) external view returns (uint256 remaining);
function decimals() external view returns (uint256 digits);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
} library Address {
function isContract(address account) internal view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
return _functionCallWithValue(target, data, value, errorMessage);
}
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
} library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
} library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(ERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*/
function safeApprove(ERC20 token, address spender, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(ERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(ERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(ERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "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");
}
}
} abstract contract TokenInterface {
address public constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
function allowance(address, address) public virtual returns (uint256);
function balanceOf(address) public virtual returns (uint256);
function approve(address, uint256) public virtual;
function transfer(address, uint256) public virtual returns (bool);
function transferFrom(address, address, uint256) public virtual returns (bool);
function deposit() public virtual payable;
function withdraw(uint256) public virtual;
} abstract contract DSAuthority {
function canCall(address src, address dst, bytes4 sig) public virtual view returns (bool);
} contract DSAuthEvents {
event LogSetAuthority(address indexed authority);
event LogSetOwner(address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
constructor() public {
owner = msg.sender;
emit LogSetOwner(msg.sender);
}
function setOwner(address owner_) public auth {
owner = owner_;
emit LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_) public auth {
authority = authority_;
emit LogSetAuthority(address(authority));
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig));
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, address(this), sig);
}
}
} contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint256 wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
assembly {
foo := calldataload(4)
bar := calldataload(36)
}
emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
_;
}
} abstract contract DSProxy is DSAuth, DSNote {
DSProxyCache public cache; // global cache for contracts
constructor(address _cacheAddr) public {
require(setCache(_cacheAddr));
}
// solhint-disable-next-line no-empty-blocks
receive() external payable {}
// use the proxy to execute calldata _data on contract _code
// function execute(bytes memory _code, bytes memory _data)
// public
// payable
// virtual
// returns (address target, bytes32 response);
function execute(address _target, bytes memory _data)
public
payable
virtual
returns (bytes32 response);
//set new cache
function setCache(address _cacheAddr) public virtual payable returns (bool);
}
contract DSProxyCache {
mapping(bytes32 => address) cache;
function read(bytes memory _code) public view returns (address) {
bytes32 hash = keccak256(_code);
return cache[hash];
}
function write(bytes memory _code) public returns (address target) {
assembly {
target := create(0, add(_code, 0x20), mload(_code))
switch iszero(extcodesize(target))
case 1 {
// throw if contract failed to deploy
revert(0, 0)
}
}
bytes32 hash = keccak256(_code);
cache[hash] = target;
}
} contract DSMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x);
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x);
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x);
}
function div(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x / y;
}
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x <= y ? x : y;
}
function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x >= y ? x : y;
}
function imin(int256 x, int256 y) internal pure returns (int256 z) {
return x <= y ? x : y;
}
function imax(int256 x, int256 y) internal pure returns (int256 z) {
return x >= y ? x : y;
}
uint256 constant WAD = 10**18;
uint256 constant RAY = 10**27;
function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, y), WAD / 2) / WAD;
}
function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, y), RAY / 2) / RAY;
}
function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, WAD), y / 2) / y;
}
function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, RAY), y / 2) / y;
}
// This famous algorithm is called "exponentiation by squaring"
// and calculates x^n with x as fixed-point and n as regular unsigned.
//
// It's O(log n), instead of O(n) for naive repeated multiplication.
//
// These facts are why it works:
//
// If n is even, then x^n = (x^2)^(n/2).
// If n is odd, then x^n = x * x^(n-1),
// and applying the equation for even x gives
// x^n = x * (x^2)^((n-1) / 2).
//
// Also, EVM division is flooring and
// floor[(n-1) / 2] = floor[n / 2].
//
function rpow(uint256 x, uint256 n) internal pure returns (uint256 z) {
z = n % 2 != 0 ? x : RAY;
for (n /= 2; n != 0; n /= 2) {
x = rmul(x, x);
if (n % 2 != 0) {
z = rmul(z, x);
}
}
}
} contract Discount {
address public owner;
mapping(address => CustomServiceFee) public serviceFees;
uint256 constant MAX_SERVICE_FEE = 400;
struct CustomServiceFee {
bool active;
uint256 amount;
}
constructor() public {
owner = msg.sender;
}
function isCustomFeeSet(address _user) public view returns (bool) {
return serviceFees[_user].active;
}
function getCustomServiceFee(address _user) public view returns (uint256) {
return serviceFees[_user].amount;
}
function setServiceFee(address _user, uint256 _fee) public {
require(msg.sender == owner, "Only owner");
require(_fee >= MAX_SERVICE_FEE || _fee == 0);
serviceFees[_user] = CustomServiceFee({active: true, amount: _fee});
}
function disableServiceFee(address _user) public {
require(msg.sender == owner, "Only owner");
serviceFees[_user] = CustomServiceFee({active: false, amount: 0});
}
}
abstract contract IFeeRecipient {
function getFeeAddr() public view virtual returns (address);
function changeWalletAddr(address _newWallet) public virtual;
} abstract contract IAToken {
function redeem(uint256 _amount) external virtual;
function balanceOf(address _owner) external virtual view returns (uint256 balance);
}
/**
* @title LendingPoolAddressesProvider contract
* @dev Main registry of addresses part of or connected to the protocol, including permissioned roles
* - Acting also as factory of proxies and admin of those, so with right to change its implementations
* - Owned by the Aave Governance
* @author Aave
**/
interface ILendingPoolAddressesProviderV2 {
event LendingPoolUpdated(address indexed newAddress);
event ConfigurationAdminUpdated(address indexed newAddress);
event EmergencyAdminUpdated(address indexed newAddress);
event LendingPoolConfiguratorUpdated(address indexed newAddress);
event LendingPoolCollateralManagerUpdated(address indexed newAddress);
event PriceOracleUpdated(address indexed newAddress);
event LendingRateOracleUpdated(address indexed newAddress);
event ProxyCreated(bytes32 id, address indexed newAddress);
event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);
function setAddress(bytes32 id, address newAddress) external;
function setAddressAsProxy(bytes32 id, address impl) external;
function getAddress(bytes32 id) external view returns (address);
function getLendingPool() external view returns (address);
function setLendingPoolImpl(address pool) external;
function getLendingPoolConfigurator() external view returns (address);
function setLendingPoolConfiguratorImpl(address configurator) external;
function getLendingPoolCollateralManager() external view returns (address);
function setLendingPoolCollateralManager(address manager) external;
function getPoolAdmin() external view returns (address);
function setPoolAdmin(address admin) external;
function getEmergencyAdmin() external view returns (address);
function setEmergencyAdmin(address admin) external;
function getPriceOracle() external view returns (address);
function setPriceOracle(address priceOracle) external;
function getLendingRateOracle() external view returns (address);
function setLendingRateOracle(address lendingRateOracle) external;
}
library DataTypes {
// refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
struct ReserveData {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
//the current stable borrow rate. Expressed in ray
uint128 currentStableBorrowRate;
uint40 lastUpdateTimestamp;
//tokens addresses
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
//address of the interest rate strategy
address interestRateStrategyAddress;
//the id of the reserve. Represents the position in the list of the active reserves
uint8 id;
}
struct ReserveConfigurationMap {
//bit 0-15: LTV
//bit 16-31: Liq. threshold
//bit 32-47: Liq. bonus
//bit 48-55: Decimals
//bit 56: Reserve is active
//bit 57: reserve is frozen
//bit 58: borrowing is enabled
//bit 59: stable rate borrowing enabled
//bit 60-63: reserved
//bit 64-79: reserve factor
uint256 data;
}
struct UserConfigurationMap {
uint256 data;
}
enum InterestRateMode {NONE, STABLE, VARIABLE}
}
interface ILendingPoolV2 {
/**
* @dev Emitted on deposit()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the deposit
* @param onBehalfOf The beneficiary of the deposit, receiving the aTokens
* @param amount The amount deposited
* @param referral The referral code used
**/
event Deposit(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referral
);
/**
* @dev Emitted on withdraw()
* @param reserve The address of the underlyng asset being withdrawn
* @param user The address initiating the withdrawal, owner of aTokens
* @param to Address that will receive the underlying
* @param amount The amount to be withdrawn
**/
event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
/**
* @dev Emitted on borrow() and flashLoan() when debt needs to be opened
* @param reserve The address of the underlying asset being borrowed
* @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
* initiator of the transaction on flashLoan()
* @param onBehalfOf The address that will be getting the debt
* @param amount The amount borrowed out
* @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable
* @param borrowRate The numeric rate at which the user has borrowed
* @param referral The referral code used
**/
event Borrow(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint256 borrowRateMode,
uint256 borrowRate,
uint16 indexed referral
);
/**
* @dev Emitted on repay()
* @param reserve The address of the underlying asset of the reserve
* @param user The beneficiary of the repayment, getting his debt reduced
* @param repayer The address of the user initiating the repay(), providing the funds
* @param amount The amount repaid
**/
event Repay(
address indexed reserve,
address indexed user,
address indexed repayer,
uint256 amount
);
/**
* @dev Emitted on swapBorrowRateMode()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user swapping his rate mode
* @param rateMode The rate mode that the user wants to swap to
**/
event Swap(address indexed reserve, address indexed user, uint256 rateMode);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on rebalanceStableBorrowRate()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user for which the rebalance has been executed
**/
event RebalanceStableBorrowRate(address indexed reserve, address indexed user);
/**
* @dev Emitted on flashLoan()
* @param target The address of the flash loan receiver contract
* @param initiator The address initiating the flash loan
* @param asset The address of the asset being flash borrowed
* @param amount The amount flash borrowed
* @param premium The fee flash borrowed
* @param referralCode The referral code used
**/
event FlashLoan(
address indexed target,
address indexed initiator,
address indexed asset,
uint256 amount,
uint256 premium,
uint16 referralCode
);
/**
* @dev Emitted when the pause is triggered.
*/
event Paused();
/**
* @dev Emitted when the pause is lifted.
*/
event Unpaused();
/**
* @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via
* LendingPoolCollateral manager using a DELEGATECALL
* This allows to have the events in the generated ABI for LendingPool.
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param liquidatedCollateralAmount The amount of collateral received by the liiquidator
* @param liquidator The address of the liquidator
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
event LiquidationCall(
address indexed collateralAsset,
address indexed debtAsset,
address indexed user,
uint256 debtToCover,
uint256 liquidatedCollateralAmount,
address liquidator,
bool receiveAToken
);
/**
* @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared
* in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,
* the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it
* gets added to the LendingPool ABI
* @param reserve The address of the underlying asset of the reserve
* @param liquidityRate The new liquidity rate
* @param stableBorrowRate The new stable borrow rate
* @param variableBorrowRate The new variable borrow rate
* @param liquidityIndex The new liquidity index
* @param variableBorrowIndex The new variable borrow index
**/
event ReserveDataUpdated(
address indexed reserve,
uint256 liquidityRate,
uint256 stableBorrowRate,
uint256 variableBorrowRate,
uint256 liquidityIndex,
uint256 variableBorrowIndex
);
/**
* @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User deposits 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to deposit
* @param amount The amount to be deposited
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
/**
* @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param asset The address of the underlying asset to withdraw
* @param amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param to Address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
**/
function withdraw(
address asset,
uint256 amount,
address to
) external;
/**
* @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already deposited enough collateral, or he was given enough allowance by a credit delegator on the
* corresponding debt token (StableDebtToken or VariableDebtToken)
* - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
* and 100 stable/variable debt tokens, depending on the `interestRateMode`
* @param asset The address of the underlying asset to borrow
* @param amount The amount to be borrowed
* @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance
**/
function borrow(
address asset,
uint256 amount,
uint256 interestRateMode,
uint16 referralCode,
address onBehalfOf
) external;
/**
* @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
* - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
**/
function repay(
address asset,
uint256 amount,
uint256 rateMode,
address onBehalfOf
) external;
/**
* @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa
* @param asset The address of the underlying asset borrowed
* @param rateMode The rate mode that the user wants to swap to
**/
function swapBorrowRateMode(address asset, uint256 rateMode) external;
/**
* @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.
* - Users can be rebalanced if the following conditions are satisfied:
* 1. Usage ratio is above 95%
* 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been
* borrowed at a stable rate and depositors are not earning enough
* @param asset The address of the underlying asset borrowed
* @param user The address of the user to be rebalanced
**/
function rebalanceStableBorrowRate(address asset, address user) external;
/**
* @dev Allows depositors to enable/disable a specific deposited asset as collateral
* @param asset The address of the underlying asset deposited
* @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise
**/
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
/**
* @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
* - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
function liquidationCall(
address collateralAsset,
address debtAsset,
address user,
uint256 debtToCover,
bool receiveAToken
) external;
/**
* @dev Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration.
* For further details please visit https://developers.aave.com
* @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface
* @param assets The addresses of the assets being flash-borrowed
* @param amounts The amounts amounts being flash-borrowed
* @param modes Types of the debt to open if the flash loan is not returned:
* 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
* 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function flashLoan(
address receiverAddress,
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata modes,
address onBehalfOf,
bytes calldata params,
uint16 referralCode
) external;
/**
* @dev Returns the user account data across all the reserves
* @param user The address of the user
* @return totalCollateralETH the total collateral in ETH of the user
* @return totalDebtETH the total debt in ETH of the user
* @return availableBorrowsETH the borrowing power left of the user
* @return currentLiquidationThreshold the liquidation threshold of the user
* @return ltv the loan to value of the user
* @return healthFactor the current health factor of the user
**/
function getUserAccountData(address user)
external
view
returns (
uint256 totalCollateralETH,
uint256 totalDebtETH,
uint256 availableBorrowsETH,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
function initReserve(
address reserve,
address aTokenAddress,
address stableDebtAddress,
address variableDebtAddress,
address interestRateStrategyAddress
) external;
function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress)
external;
function setConfiguration(address reserve, uint256 configuration) external;
/**
* @dev Returns the configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The configuration of the reserve
**/
function getConfiguration(address asset) external view returns (DataTypes.ReserveConfigurationMap memory);
/**
* @dev Returns the configuration of the user across all the reserves
* @param user The user address
* @return The configuration of the user
**/
function getUserConfiguration(address user) external view returns (DataTypes.UserConfigurationMap memory);
/**
* @dev Returns the normalized income normalized income of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The reserve's normalized income
*/
function getReserveNormalizedIncome(address asset) external view returns (uint256);
/**
* @dev Returns the normalized variable debt per unit of asset
* @param asset The address of the underlying asset of the reserve
* @return The reserve normalized variable debt
*/
function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);
/**
* @dev Returns the state and configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The state of the reserve
**/
function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);
function finalizeTransfer(
address asset,
address from,
address to,
uint256 amount,
uint256 balanceFromAfter,
uint256 balanceToBefore
) external;
function getReservesList() external view returns (address[] memory);
function getAddressesProvider() external view returns (ILendingPoolAddressesProviderV2);
function setPause(bool val) external;
function paused() external view returns (bool);
} /************
@title IPriceOracleGetterAave interface
@notice Interface for the Aave price oracle.*/
abstract contract IPriceOracleGetterAave {
function getAssetPrice(address _asset) external virtual view returns (uint256);
function getAssetsPrices(address[] calldata _assets) external virtual view returns(uint256[] memory);
function getSourceOfAsset(address _asset) external virtual view returns(address);
function getFallbackOracle() external virtual view returns(address);
}
abstract contract IAaveProtocolDataProviderV2 {
struct TokenData {
string symbol;
address tokenAddress;
}
function getAllReservesTokens() external virtual view returns (TokenData[] memory);
function getAllATokens() external virtual view returns (TokenData[] memory);
function getReserveConfigurationData(address asset)
external virtual
view
returns (
uint256 decimals,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus,
uint256 reserveFactor,
bool usageAsCollateralEnabled,
bool borrowingEnabled,
bool stableBorrowRateEnabled,
bool isActive,
bool isFrozen
);
function getReserveData(address asset)
external virtual
view
returns (
uint256 availableLiquidity,
uint256 totalStableDebt,
uint256 totalVariableDebt,
uint256 liquidityRate,
uint256 variableBorrowRate,
uint256 stableBorrowRate,
uint256 averageStableBorrowRate,
uint256 liquidityIndex,
uint256 variableBorrowIndex,
uint40 lastUpdateTimestamp
);
function getUserReserveData(address asset, address user)
external virtual
view
returns (
uint256 currentATokenBalance,
uint256 currentStableDebt,
uint256 currentVariableDebt,
uint256 principalStableDebt,
uint256 scaledVariableDebt,
uint256 stableBorrowRate,
uint256 liquidityRate,
uint40 stableRateLastUpdated,
bool usageAsCollateralEnabled
);
function getReserveTokensAddresses(address asset)
external virtual
view
returns (
address aTokenAddress,
address stableDebtTokenAddress,
address variableDebtTokenAddress
);
} contract AdminAuth {
using SafeERC20 for ERC20;
address public owner;
address public admin;
modifier onlyOwner() {
require(owner == msg.sender);
_;
}
modifier onlyAdmin() {
require(admin == msg.sender);
_;
}
constructor() public {
owner = 0xBc841B0dE0b93205e912CFBBd1D0c160A1ec6F00;
admin = 0x25eFA336886C74eA8E282ac466BdCd0199f85BB9;
}
/// @notice Admin is set by owner first time, after that admin is super role and has permission to change owner
/// @param _admin Address of multisig that becomes admin
function setAdminByOwner(address _admin) public {
require(msg.sender == owner);
require(admin == address(0));
admin = _admin;
}
/// @notice Admin is able to set new admin
/// @param _admin Address of multisig that becomes new admin
function setAdminByAdmin(address _admin) public {
require(msg.sender == admin);
admin = _admin;
}
/// @notice Admin is able to change owner
/// @param _owner Address of new owner
function setOwnerByAdmin(address _owner) public {
require(msg.sender == admin);
owner = _owner;
}
/// @notice Destroy the contract
function kill() public onlyOwner {
selfdestruct(payable(owner));
}
/// @notice withdraw stuck funds
function withdrawStuckFunds(address _token, uint _amount) public onlyOwner {
if (_token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) {
payable(owner).transfer(_amount);
} else {
ERC20(_token).safeTransfer(owner, _amount);
}
}
} contract BotRegistry is AdminAuth {
mapping (address => bool) public botList;
constructor() public {
botList[0x776B4a13093e30B05781F97F6A4565B6aa8BE330] = true;
botList[0xAED662abcC4FA3314985E67Ea993CAD064a7F5cF] = true;
botList[0xa5d330F6619d6bF892A5B87D80272e1607b3e34D] = true;
botList[0x5feB4DeE5150B589a7f567EA7CADa2759794A90A] = true;
botList[0x7ca06417c1d6f480d3bB195B80692F95A6B66158] = true;
}
function setBot(address _botAddr, bool _state) public onlyOwner {
botList[_botAddr] = _state;
}
} contract AaveHelperV2 is DSMath {
using SafeERC20 for ERC20;
IFeeRecipient public constant feeRecipient = IFeeRecipient(0x39C4a92Dc506300c3Ea4c67ca4CA611102ee6F2A);
address public constant DISCOUNT_ADDR = 0x1b14E8D511c9A4395425314f849bD737BAF8208F;
address public constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // mainnet
uint public constant MANUAL_SERVICE_FEE = 400; // 0.25% Fee
uint public constant AUTOMATIC_SERVICE_FEE = 333; // 0.3% Fee
address public constant BOT_REGISTRY_ADDRESS = 0x637726f8b08a7ABE3aE3aCaB01A80E2d8ddeF77B;
address public constant ETH_ADDR = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
uint public constant NINETY_NINE_PERCENT_WEI = 990000000000000000;
uint16 public constant AAVE_REFERRAL_CODE = 64;
uint public constant STABLE_ID = 1;
uint public constant VARIABLE_ID = 2;
/// @notice Calculates the gas cost for transaction
/// @param _oracleAddress address of oracle used
/// @param _amount Amount that is converted
/// @param _user Actuall user addr not DSProxy
/// @param _gasCost Ether amount of gas we are spending for tx
/// @param _tokenAddr token addr. of token we are getting for the fee
/// @return gasCost The amount we took for the gas cost
function getGasCost(address _oracleAddress, uint _amount, address _user, uint _gasCost, address _tokenAddr) internal returns (uint gasCost) {
if (_gasCost == 0) return 0;
// in case its ETH, we need to get price for WETH
// everywhere else we still use ETH as thats the token we have in this moment
address priceToken = _tokenAddr == ETH_ADDR ? WETH_ADDRESS : _tokenAddr;
uint256 price = IPriceOracleGetterAave(_oracleAddress).getAssetPrice(priceToken);
_gasCost = wdiv(_gasCost, price) / (10 ** (18 - _getDecimals(_tokenAddr)));
gasCost = _gasCost;
// gas cost can't go over 20% of the whole amount
if (gasCost > (_amount / 5)) {
gasCost = _amount / 5;
}
address walletAddr = feeRecipient.getFeeAddr();
if (_tokenAddr == ETH_ADDR) {
payable(walletAddr).transfer(gasCost);
} else {
ERC20(_tokenAddr).safeTransfer(walletAddr, gasCost);
}
}
/// @notice Returns the owner of the DSProxy that called the contract
function getUserAddress() internal view returns (address) {
DSProxy proxy = DSProxy(payable(address(this)));
return proxy.owner();
}
/// @notice Approves token contract to pull underlying tokens from the DSProxy
/// @param _tokenAddr Token we are trying to approve
/// @param _caller Address which will gain the approval
function approveToken(address _tokenAddr, address _caller) internal {
if (_tokenAddr != ETH_ADDR) {
ERC20(_tokenAddr).safeApprove(_caller, uint256(-1));
}
}
/// @notice Send specific amount from contract to specific user
/// @param _token Token we are trying to send
/// @param _user User that should receive funds
/// @param _amount Amount that should be sent
function sendContractBalance(address _token, address _user, uint _amount) internal {
if (_amount == 0) return;
if (_token == ETH_ADDR) {
payable(_user).transfer(_amount);
} else {
ERC20(_token).safeTransfer(_user, _amount);
}
}
function sendFullContractBalance(address _token, address _user) internal {
if (_token == ETH_ADDR) {
sendContractBalance(_token, _user, address(this).balance);
} else {
sendContractBalance(_token, _user, ERC20(_token).balanceOf(address(this)));
}
}
function _getDecimals(address _token) internal view returns (uint256) {
if (_token == ETH_ADDR) return 18;
return ERC20(_token).decimals();
}
function getDataProvider(address _market) internal view returns(IAaveProtocolDataProviderV2) {
return IAaveProtocolDataProviderV2(ILendingPoolAddressesProviderV2(_market).getAddress(0x0100000000000000000000000000000000000000000000000000000000000000));
}
} interface ExchangeInterfaceV3 {
function sell(address _srcAddr, address _destAddr, uint _srcAmount, bytes memory _additionalData) external payable returns (uint);
function buy(address _srcAddr, address _destAddr, uint _destAmount, bytes memory _additionalData) external payable returns(uint);
function getSellRate(address _srcAddr, address _destAddr, uint _srcAmount, bytes memory _additionalData) external view returns (uint);
function getBuyRate(address _srcAddr, address _destAddr, uint _srcAmount, bytes memory _additionalData) external view returns (uint);
} contract ZrxAllowlist is AdminAuth {
mapping (address => bool) public zrxAllowlist;
mapping(address => bool) private nonPayableAddrs;
constructor() public {
zrxAllowlist[0x6958F5e95332D93D21af0D7B9Ca85B8212fEE0A5] = true;
zrxAllowlist[0x61935CbDd02287B511119DDb11Aeb42F1593b7Ef] = true;
zrxAllowlist[0xDef1C0ded9bec7F1a1670819833240f027b25EfF] = true;
zrxAllowlist[0x080bf510FCbF18b91105470639e9561022937712] = true;
nonPayableAddrs[0x080bf510FCbF18b91105470639e9561022937712] = true;
}
function setAllowlistAddr(address _zrxAddr, bool _state) public onlyOwner {
zrxAllowlist[_zrxAddr] = _state;
}
function isZrxAddr(address _zrxAddr) public view returns (bool) {
return zrxAllowlist[_zrxAddr];
}
function addNonPayableAddr(address _nonPayableAddr) public onlyOwner {
nonPayableAddrs[_nonPayableAddr] = true;
}
function removeNonPayableAddr(address _nonPayableAddr) public onlyOwner {
nonPayableAddrs[_nonPayableAddr] = false;
}
function isNonPayableAddr(address _addr) public view returns(bool) {
return nonPayableAddrs[_addr];
}
}
contract DFSExchangeData {
// first is empty to keep the legacy order in place
enum ExchangeType { _, OASIS, KYBER, UNISWAP, ZEROX }
enum ActionType { SELL, BUY }
struct OffchainData {
address wrapper;
address exchangeAddr;
address allowanceTarget;
uint256 price;
uint256 protocolFee;
bytes callData;
}
struct ExchangeData {
address srcAddr;
address destAddr;
uint256 srcAmount;
uint256 destAmount;
uint256 minPrice;
uint256 dfsFeeDivider; // service fee divider
address user; // user to check special fee
address wrapper;
bytes wrapperData;
OffchainData offchainData;
}
function packExchangeData(ExchangeData memory _exData) public pure returns(bytes memory) {
return abi.encode(_exData);
}
function unpackExchangeData(bytes memory _data) public pure returns(ExchangeData memory _exData) {
_exData = abi.decode(_data, (ExchangeData));
}
} contract DFSExchangeHelper {
string public constant ERR_OFFCHAIN_DATA_INVALID = "Offchain data invalid";
using SafeERC20 for ERC20;
address public constant KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address public constant EXCHANGE_WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
IFeeRecipient public constant _feeRecipient = IFeeRecipient(0x39C4a92Dc506300c3Ea4c67ca4CA611102ee6F2A);
address public constant DISCOUNT_ADDRESS = 0x1b14E8D511c9A4395425314f849bD737BAF8208F;
address public constant SAVER_EXCHANGE_REGISTRY = 0x25dd3F51e0C3c3Ff164DDC02A8E4D65Bb9cBB12D;
address public constant ZRX_ALLOWLIST_ADDR = 0x4BA1f38427b33B8ab7Bb0490200dAE1F1C36823F;
function getDecimals(address _token) internal view returns (uint256) {
if (_token == KYBER_ETH_ADDRESS) return 18;
return ERC20(_token).decimals();
}
function getBalance(address _tokenAddr) internal view returns (uint balance) {
if (_tokenAddr == KYBER_ETH_ADDRESS) {
balance = address(this).balance;
} else {
balance = ERC20(_tokenAddr).balanceOf(address(this));
}
}
function sendLeftover(address _srcAddr, address _destAddr, address payable _to) internal {
// send back any leftover ether or tokens
if (address(this).balance > 0) {
_to.transfer(address(this).balance);
}
if (getBalance(_srcAddr) > 0) {
ERC20(_srcAddr).safeTransfer(_to, getBalance(_srcAddr));
}
if (getBalance(_destAddr) > 0) {
ERC20(_destAddr).safeTransfer(_to, getBalance(_destAddr));
}
}
/// @notice Takes a feePercentage and sends it to wallet
/// @param _amount Dai amount of the whole trade
/// @param _user Address of the user
/// @param _token Address of the token
/// @param _dfsFeeDivider Dfs fee divider
/// @return feeAmount Amount in Dai owner earned on the fee
function getFee(uint256 _amount, address _user, address _token, uint256 _dfsFeeDivider) internal returns (uint256 feeAmount) {
if (_dfsFeeDivider != 0 && Discount(DISCOUNT_ADDRESS).isCustomFeeSet(_user)) {
_dfsFeeDivider = Discount(DISCOUNT_ADDRESS).getCustomServiceFee(_user);
}
if (_dfsFeeDivider == 0) {
feeAmount = 0;
} else {
feeAmount = _amount / _dfsFeeDivider;
// fee can't go over 10% of the whole amount
if (feeAmount > (_amount / 10)) {
feeAmount = _amount / 10;
}
address walletAddr = _feeRecipient.getFeeAddr();
if (_token == KYBER_ETH_ADDRESS) {
payable(walletAddr).transfer(feeAmount);
} else {
ERC20(_token).safeTransfer(walletAddr, feeAmount);
}
}
}
function sliceUint(bytes memory bs, uint256 start) internal pure returns (uint256) {
require(bs.length >= start + 32, "slicing out of range");
uint256 x;
assembly {
x := mload(add(bs, add(0x20, start)))
}
return x;
}
function writeUint256(bytes memory _b, uint256 _index, uint _input) internal pure {
if (_b.length < _index + 32) {
revert(ERR_OFFCHAIN_DATA_INVALID);
}
bytes32 input = bytes32(_input);
_index += 32;
// Read the bytes32 from array memory
assembly {
mstore(add(_b, _index), input)
}
}
/// @notice Converts Kybers Eth address -> Weth
/// @param _src Input address
function ethToWethAddr(address _src) internal pure returns (address) {
return _src == KYBER_ETH_ADDRESS ? EXCHANGE_WETH_ADDRESS : _src;
}
} contract SaverExchangeRegistry is AdminAuth {
mapping(address => bool) private wrappers;
constructor() public {
wrappers[0x880A845A85F843a5c67DB2061623c6Fc3bB4c511] = true;
wrappers[0x4c9B55f2083629A1F7aDa257ae984E03096eCD25] = true;
wrappers[0x42A9237b872368E1bec4Ca8D26A928D7d39d338C] = true;
}
function addWrapper(address _wrapper) public onlyOwner {
wrappers[_wrapper] = true;
}
function removeWrapper(address _wrapper) public onlyOwner {
wrappers[_wrapper] = false;
}
function isWrapper(address _wrapper) public view returns(bool) {
return wrappers[_wrapper];
}
}
abstract contract OffchainWrapperInterface is DFSExchangeData {
function takeOrder(
ExchangeData memory _exData,
ActionType _type
) virtual public payable returns (bool success, uint256);
}
contract DFSExchangeCore is DFSExchangeHelper, DSMath, DFSExchangeData {
string public constant ERR_SLIPPAGE_HIT = "Slippage hit";
string public constant ERR_DEST_AMOUNT_MISSING = "Dest amount missing";
string public constant ERR_WRAPPER_INVALID = "Wrapper invalid";
string public constant ERR_NOT_ZEROX_EXCHANGE = "Zerox exchange invalid";
/// @notice Internal method that preforms a sell on 0x/on-chain
/// @dev Usefull for other DFS contract to integrate for exchanging
/// @param exData Exchange data struct
/// @return (address, uint) Address of the wrapper used and destAmount
function _sell(ExchangeData memory exData) internal returns (address, uint) {
address wrapper;
uint swapedTokens;
bool success;
// if selling eth, convert to weth
if (exData.srcAddr == KYBER_ETH_ADDRESS) {
exData.srcAddr = ethToWethAddr(exData.srcAddr);
TokenInterface(EXCHANGE_WETH_ADDRESS).deposit{value: exData.srcAmount}();
}
exData.srcAmount -= getFee(exData.srcAmount, exData.user, exData.srcAddr, exData.dfsFeeDivider);
// Try 0x first and then fallback on specific wrapper
if (exData.offchainData.price > 0) {
(success, swapedTokens) = takeOrder(exData, ActionType.SELL);
if (success) {
wrapper = exData.offchainData.exchangeAddr;
}
}
// fallback to desired wrapper if 0x failed
if (!success) {
swapedTokens = saverSwap(exData, ActionType.SELL);
wrapper = exData.wrapper;
}
// if anything is left in weth, pull it to user as eth
if (getBalance(EXCHANGE_WETH_ADDRESS) > 0) {
TokenInterface(EXCHANGE_WETH_ADDRESS).withdraw(
TokenInterface(EXCHANGE_WETH_ADDRESS).balanceOf(address(this))
);
}
if (exData.destAddr == EXCHANGE_WETH_ADDRESS) {
require(getBalance(KYBER_ETH_ADDRESS) >= wmul(exData.minPrice, exData.srcAmount), ERR_SLIPPAGE_HIT);
} else {
require(getBalance(exData.destAddr) >= wmul(exData.minPrice, exData.srcAmount), ERR_SLIPPAGE_HIT);
}
return (wrapper, swapedTokens);
}
/// @notice Internal method that preforms a buy on 0x/on-chain
/// @dev Usefull for other DFS contract to integrate for exchanging
/// @param exData Exchange data struct
/// @return (address, uint) Address of the wrapper used and srcAmount
function _buy(ExchangeData memory exData) internal returns (address, uint) {
address wrapper;
uint swapedTokens;
bool success;
require(exData.destAmount != 0, ERR_DEST_AMOUNT_MISSING);
exData.srcAmount -= getFee(exData.srcAmount, exData.user, exData.srcAddr, exData.dfsFeeDivider);
// if selling eth, convert to weth
if (exData.srcAddr == KYBER_ETH_ADDRESS) {
exData.srcAddr = ethToWethAddr(exData.srcAddr);
TokenInterface(EXCHANGE_WETH_ADDRESS).deposit{value: exData.srcAmount}();
}
if (exData.offchainData.price > 0) {
(success, swapedTokens) = takeOrder(exData, ActionType.BUY);
if (success) {
wrapper = exData.offchainData.exchangeAddr;
}
}
// fallback to desired wrapper if 0x failed
if (!success) {
swapedTokens = saverSwap(exData, ActionType.BUY);
wrapper = exData.wrapper;
}
// if anything is left in weth, pull it to user as eth
if (getBalance(EXCHANGE_WETH_ADDRESS) > 0) {
TokenInterface(EXCHANGE_WETH_ADDRESS).withdraw(
TokenInterface(EXCHANGE_WETH_ADDRESS).balanceOf(address(this))
);
}
if (exData.destAddr == EXCHANGE_WETH_ADDRESS) {
require(getBalance(KYBER_ETH_ADDRESS) >= exData.destAmount, ERR_SLIPPAGE_HIT);
} else {
require(getBalance(exData.destAddr) >= exData.destAmount, ERR_SLIPPAGE_HIT);
}
return (wrapper, getBalance(exData.destAddr));
}
/// @notice Takes order from 0x and returns bool indicating if it is successful
/// @param _exData Exchange data
function takeOrder(
ExchangeData memory _exData,
ActionType _type
) private returns (bool success, uint256) {
if (!ZrxAllowlist(ZRX_ALLOWLIST_ADDR).isZrxAddr(_exData.offchainData.exchangeAddr)) {
return (false, 0);
}
if (!SaverExchangeRegistry(SAVER_EXCHANGE_REGISTRY).isWrapper(_exData.offchainData.wrapper)) {
return (false, 0);
}
// send src amount
ERC20(_exData.srcAddr).safeTransfer(_exData.offchainData.wrapper, _exData.srcAmount);
return OffchainWrapperInterface(_exData.offchainData.wrapper).takeOrder{value: _exData.offchainData.protocolFee}(_exData, _type);
}
/// @notice Calls wraper contract for exchage to preform an on-chain swap
/// @param _exData Exchange data struct
/// @param _type Type of action SELL|BUY
/// @return swapedTokens For Sell that the destAmount, for Buy thats the srcAmount
function saverSwap(ExchangeData memory _exData, ActionType _type) internal returns (uint swapedTokens) {
require(SaverExchangeRegistry(SAVER_EXCHANGE_REGISTRY).isWrapper(_exData.wrapper), ERR_WRAPPER_INVALID);
ERC20(_exData.srcAddr).safeTransfer(_exData.wrapper, _exData.srcAmount);
if (_type == ActionType.SELL) {
swapedTokens = ExchangeInterfaceV3(_exData.wrapper).
sell(_exData.srcAddr, _exData.destAddr, _exData.srcAmount, _exData.wrapperData);
} else {
swapedTokens = ExchangeInterfaceV3(_exData.wrapper).
buy(_exData.srcAddr, _exData.destAddr, _exData.destAmount, _exData.wrapperData);
}
}
// solhint-disable-next-line no-empty-blocks
receive() external virtual payable {}
} contract DefisaverLogger {
event LogEvent(
address indexed contractAddress,
address indexed caller,
string indexed logName,
bytes data
);
// solhint-disable-next-line func-name-mixedcase
function Log(address _contract, address _caller, string memory _logName, bytes memory _data)
public
{
emit LogEvent(_contract, _caller, _logName, _data);
}
}
/// @title Import Aave position from account to wallet
contract AaveSaverReceiverOV2 is AaveHelperV2, AdminAuth, DFSExchangeCore {
using SafeERC20 for ERC20;
address public constant DEFISAVER_LOGGER = 0x5c55B921f590a89C1Ebe84dF170E655a82b62126;
address public constant AAVE_BASIC_PROXY = 0xCD47e74A717B882EFb54A3e17B59A5b1e31fd3c3;
function boost(
ExchangeData memory _exchangeData,
address _market,
uint256 _gasCost,
address _proxy
) internal {
uint256 swappedAmount = _exchangeData.srcAmount;
if (_exchangeData.srcAddr != _exchangeData.destAddr) {
(, swappedAmount) = _sell(_exchangeData);
}
address user = DSAuth(_proxy).owner();
swappedAmount -= getGasCost(
ILendingPoolAddressesProviderV2(_market).getPriceOracle(),
swappedAmount,
user,
_gasCost,
_exchangeData.destAddr
);
// if its eth we need to send it to the basic proxy, if not, we need to approve users proxy to pull tokens
uint256 msgValue = 0;
address token = _exchangeData.destAddr;
// sell always return eth, but deposit differentiate eth vs weth, so we change weth address to eth when we are depoisting
if (_exchangeData.destAddr == ETH_ADDR || _exchangeData.destAddr == WETH_ADDRESS) {
msgValue = swappedAmount;
token = ETH_ADDR;
} else {
ERC20(_exchangeData.destAddr).safeApprove(_proxy, swappedAmount);
}
// deposit collateral on behalf of user
DSProxy(payable(_proxy)).execute{value: msgValue}(
AAVE_BASIC_PROXY,
abi.encodeWithSignature(
"deposit(address,address,uint256)",
_market,
token,
swappedAmount
)
);
logEvent("AaveV2Boost", _exchangeData, swappedAmount);
}
function repay(
ExchangeData memory _exchangeData,
address _market,
uint256 _gasCost,
address _proxy,
uint256 _rateMode,
uint256 _aaveFlashlLoanFee
) internal {
// we will withdraw exactly the srcAmount, as fee we keep before selling
uint256 valueToWithdraw = _exchangeData.srcAmount;
// take out the fee wee need to pay and sell the rest
_exchangeData.srcAmount = _exchangeData.srcAmount - _aaveFlashlLoanFee;
uint256 swappedAmount = _exchangeData.srcAmount;
// don't sell if its the same token
if (_exchangeData.srcAddr != _exchangeData.destAddr) {
(, swappedAmount) = _sell(_exchangeData);
}
address user = DSAuth(_proxy).owner();
swappedAmount -= getGasCost(
ILendingPoolAddressesProviderV2(_market).getPriceOracle(),
swappedAmount,
user,
_gasCost,
_exchangeData.destAddr
);
// set protocol fee left to eth balance of this address
// but if destAddr is eth or weth, this also includes that value so we need to substract it
// doing this after taking gas cost so it doesn't take it into account
uint256 protocolFeeLeft = address(this).balance;
// if its eth we need to send it to the basic proxy, if not, we need to approve basic proxy to pull tokens
uint256 msgValue = 0;
if (_exchangeData.destAddr == ETH_ADDR || _exchangeData.destAddr == WETH_ADDRESS) {
protocolFeeLeft -= swappedAmount;
msgValue = swappedAmount;
} else {
ERC20(_exchangeData.destAddr).safeApprove(_proxy, swappedAmount);
}
// first payback the loan with swapped amount
// this payback will return funds that left directly to the user
DSProxy(payable(_proxy)).execute{value: msgValue}(
AAVE_BASIC_PROXY,
abi.encodeWithSignature(
"paybackAndReturnToUser(address,address,uint256,uint256,address)",
_market,
_exchangeData.destAddr,
swappedAmount,
_rateMode,
user
)
);
// pull the amount we flash loaned in collateral to be able to payback the debt
DSProxy(payable(_proxy)).execute(
AAVE_BASIC_PROXY,
abi.encodeWithSignature(
"withdraw(address,address,uint256)",
_market,
_exchangeData.srcAddr,
valueToWithdraw
)
);
logEvent("AaveV2Repay", _exchangeData, swappedAmount);
}
function executeOperation(
address[] calldata,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) public returns (bool) {
(
bytes memory exchangeDataBytes,
address market,
uint256 gasCost,
uint256 rateMode,
bool isRepay,
address proxy
) = abi.decode(params, (bytes, address, uint256, uint256, bool, address));
address lendingPool = ILendingPoolAddressesProviderV2(market).getLendingPool();
require(msg.sender == lendingPool, "Callbacks only allowed from Aave");
require(initiator == proxy, "initiator isn't proxy");
ExchangeData memory exData = unpackExchangeData(exchangeDataBytes);
exData.user = DSAuth(proxy).owner();
exData.dfsFeeDivider = MANUAL_SERVICE_FEE;
if (BotRegistry(BOT_REGISTRY_ADDRESS).botList(tx.origin)) {
exData.dfsFeeDivider = AUTOMATIC_SERVICE_FEE;
}
// this is to avoid stack too deep
uint256 fee = premiums[0];
uint256 totalValueToReturn = exData.srcAmount + fee;
// if its repay, we are using regular flash loan and payback the premiums
if (isRepay) {
repay(exData, market, gasCost, proxy, rateMode, fee);
address token = exData.srcAddr;
if (token == ETH_ADDR || token == WETH_ADDRESS) {
// deposit eth, get weth and return to sender
TokenInterface(WETH_ADDRESS).deposit.value(totalValueToReturn)();
token = WETH_ADDRESS;
}
ERC20(token).safeApprove(lendingPool, totalValueToReturn);
} else {
boost(exData, market, gasCost, proxy);
}
tx.origin.transfer(address(this).balance);
return true;
}
function logEvent(string memory _name, ExchangeData memory _exchangeData, uint _swappedAmount) internal {
DefisaverLogger(DEFISAVER_LOGGER).Log(
address(this),
msg.sender,
_name,
abi.encode(_exchangeData.srcAddr, _exchangeData.destAddr, _exchangeData.srcAmount, _swappedAmount)
);
}
/// @dev allow contract to receive eth from sell
receive() external payable override {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"AAVE_BASIC_PROXY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"AAVE_REFERRAL_CODE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"AUTOMATIC_SERVICE_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BOT_REGISTRY_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFISAVER_LOGGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISCOUNT_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISCOUNT_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_DEST_AMOUNT_MISSING","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_NOT_ZEROX_EXCHANGE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_OFFCHAIN_DATA_INVALID","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_SLIPPAGE_HIT","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_WRAPPER_INVALID","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXCHANGE_WETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KYBER_ETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANUAL_SERVICE_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NINETY_NINE_PERCENT_WEI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SAVER_EXCHANGE_REGISTRY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STABLE_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VARIABLE_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ZRX_ALLOWLIST_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_feeRecipient","outputs":[{"internalType":"contract IFeeRecipient","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"premiums","type":"uint256[]"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"executeOperation","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"contract IFeeRecipient","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"srcAddr","type":"address"},{"internalType":"address","name":"destAddr","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"uint256","name":"dfsFeeDivider","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"bytes","name":"wrapperData","type":"bytes"},{"components":[{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"address","name":"exchangeAddr","type":"address"},{"internalType":"address","name":"allowanceTarget","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"protocolFee","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct DFSExchangeData.OffchainData","name":"offchainData","type":"tuple"}],"internalType":"struct DFSExchangeData.ExchangeData","name":"_exData","type":"tuple"}],"name":"packExchangeData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdminByAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdminByOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwnerByAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"unpackExchangeData","outputs":[{"components":[{"internalType":"address","name":"srcAddr","type":"address"},{"internalType":"address","name":"destAddr","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"uint256","name":"dfsFeeDivider","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"bytes","name":"wrapperData","type":"bytes"},{"components":[{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"address","name":"exchangeAddr","type":"address"},{"internalType":"address","name":"allowanceTarget","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"protocolFee","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct DFSExchangeData.OffchainData","name":"offchainData","type":"tuple"}],"internalType":"struct DFSExchangeData.ExchangeData","name":"_exData","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawStuckFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405234801561001057600080fd5b50600080546001600160a01b031990811673bc841b0de0b93205e912cfbbd1d0c160a1ec6f0017909155600180549091167325efa336886c74ea8e282ac466bdcd0199f85bb9179055612fb2806100686000396000f3fe6080604052600436106101fd5760003560e01c80637b925ab11161010d578063a46a66c9116100a0578063c50ebaf81161006f578063c50ebaf8146104b1578063cc694d48146104c6578063d4f922dc146104db578063deca5f88146104f0578063f851a4401461051057610204565b8063a46a66c9146103b9578063a7304bf714610467578063ae08fd1014610487578063b13cdb201461049c57610204565b80638da5cb5b116100dc5780638da5cb5b146103f8578063920f5c841461040d578063a342f2381461037a578063a3b8e5d11461043a57610204565b80637b925ab1146103b957806381b9428014610209578063870e44d9146103ce5780638c8a7958146103e357610204565b8063314b633211610190578063449b9ffa1161015f578063449b9ffa14610365578063469048401461037a5780634d2ab9dc1461038f578063526d6461146103a45780637753f47b146102dc57610204565b8063314b63321461030657806339df18781461031b5780633a1283221461033057806341c0e1b51461035057610204565b80631e48907b116101cc5780631e48907b146102a5578063278d5831146102c757806329f7fc9e146102dc5780632ba38bcb146102f157610204565b8063040141e51461020957806304c9805c1461023457806305a363de1461025657806308d4f52a1461027857610204565b3661020457005b600080fd5b34801561021557600080fd5b5061021e610525565b60405161022b9190612bfb565b60405180910390f35b34801561024057600080fd5b5061024961053d565b60405161022b9190612eb2565b34801561026257600080fd5b5061026b610543565b60405161022b9190612ea3565b34801561028457600080fd5b506102986102933660046128a3565b610548565b60405161022b9190612d6c565b3480156102b157600080fd5b506102c56102c0366004612628565b610572565b005b3480156102d357600080fd5b506102986105ab565b3480156102e857600080fd5b5061021e6105d3565b3480156102fd57600080fd5b506102496105e5565b34801561031257600080fd5b5061021e6105ea565b34801561032757600080fd5b5061021e610602565b34801561033c57600080fd5b506102c561034b366004612660565b61061a565b34801561035c57600080fd5b506102c56106ad565b34801561037157600080fd5b506102986106d2565b34801561038657600080fd5b5061021e610704565b34801561039b57600080fd5b5061024961071c565b3480156103b057600080fd5b5061021e610722565b3480156103c557600080fd5b5061021e61073a565b3480156103da57600080fd5b50610249610752565b3480156103ef57600080fd5b5061021e61075e565b34801561040457600080fd5b5061021e610776565b34801561041957600080fd5b5061042d61042836600461268b565b610785565b60405161022b9190612d61565b34801561044657600080fd5b5061045a6104553660046127e9565b610b19565b60405161022b9190612e64565b34801561047357600080fd5b506102c5610482366004612628565b610b3b565b34801561049357600080fd5b50610298610b74565b3480156104a857600080fd5b5061021e610ba5565b3480156104bd57600080fd5b50610298610bbd565b3480156104d257600080fd5b50610298610bec565b3480156104e757600080fd5b50610249610c17565b3480156104fc57600080fd5b506102c561050b366004612628565b610c1c565b34801561051c57600080fd5b5061021e610c49565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b61014d81565b604081565b60608160405160200161055b9190612e64565b60405160208183030381529060405290505b919050565b6001546001600160a01b0316331461058957600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525081565b600080516020612f5d83398151915281565b600181565b7325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d81565b735c55b921f590a89c1ebe84df170e655a82b6212681565b6000546001600160a01b0316331461063157600080fd5b600080516020612f5d8339815191526001600160a01b038316141561068f57600080546040516001600160a01b039091169183156108fc02918491818181858888f19350505050158015610689573d6000803e3d6000fd5b506106a9565b6000546106a9906001600160a01b03848116911683610c58565b5050565b6000546001600160a01b031633146106c457600080fd5b6000546001600160a01b0316ff5b6040518060400160405280601681526020017516995c9bde08195e18da185b99d9481a5b9d985b1a5960521b81525081565b7339c4a92dc506300c3ea4c67ca4ca611102ee6f2a81565b61019081565b73637726f8b08a7abe3ae3acab01a80e2d8ddef77b81565b731b14e8d511c9a4395425314f849bd737baf8208f81565b670dbd2fc137a3000081565b734ba1f38427b33b8ab7bb0490200dae1f1c36823f81565b6000546001600160a01b031681565b60006060818080808061079a888a018a61281c565b9550955095509550955095506000856001600160a01b0316630261bf8b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156107e157600080fd5b505afa1580156107f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108199190612644565b9050336001600160a01b0382161461084c5760405162461bcd60e51b815260040161084390612d7f565b60405180910390fd5b816001600160a01b03168b6001600160a01b03161461087d5760405162461bcd60e51b815260040161084390612e35565b61088561233f565b61088e88610b19565b9050826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108c957600080fd5b505afa1580156108dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109019190612644565b6001600160a01b031660c082015261019060a08201526040516320eb73ed60e11b815273637726f8b08a7abe3ae3acab01a80e2d8ddef77b906341d6e7da9061094e903290600401612bfb565b60206040518083038186803b15801561096657600080fd5b505afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190612788565b156109ac5761014d60a08201525b60008e8e60008181106109bb57fe5b90506020020135905060008183604001510190508515610ac5576109e3838a8a888b87610cb3565b82516001600160a01b038116600080516020612f5d8339815191521480610a2657506001600160a01b03811673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b15610aab5773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b505050505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290505b610abf6001600160a01b038216868461104c565b50610ad1565b610ad1838a8a8861108b565b60405132904780156108fc02916000818181858888f19350505050158015610afd573d6000803e3d6000fd5b5060019a50505050505050505050509998505050505050505050565b610b2161233f565b81806020019051810190610b3591906129ab565b92915050565b6001546001600160a01b03163314610b5257600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6040518060400160405280601581526020017413d99998da185a5b8819185d18481a5b9d985b1a59605a1b81525081565b73cd47e74a717b882efb54a3e17b59a5b1e31fd3c381565b604051806040016040528060138152602001724465737420616d6f756e74206d697373696e6760681b81525081565b6040518060400160405280600f81526020016e15dc985c1c195c881a5b9d985b1a59608a1b81525081565b600281565b6000546001600160a01b03163314610c3357600080fd5b6001546001600160a01b031615610b5257600080fd5b6001546001600160a01b031681565b610cae8363a9059cbb60e01b8484604051602401610c77929190612d48565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611341565b505050565b60408601805182810391829052602088015188519192916001600160a01b03908116911614610ce957610ce5886113d0565b9150505b6000856001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d2457600080fd5b505afa158015610d38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5c9190612644565b9050610ddf886001600160a01b031663fca513a86040518163ffffffff1660e01b815260040160206040518083038186803b158015610d9a57600080fd5b505afa158015610dae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd29190612644565b83838a8d6020015161170b565b60208a015192039147906000906001600160a01b0316600080516020612f5d8339815191521480610e30575060208b01516001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b15610e3f575082900382610e58565b60208b0151610e58906001600160a01b0316898661104c565b876001600160a01b0316631cff79cd8273cd47e74a717b882efb54a3e17b59a5b1e31fd3c38d8f60200151898d8a604051602401610e9a959493929190612cd8565b60408051601f198184030181529181526020820180516001600160e01b0316632c6951f360e21b1790525160e085901b6001600160e01b0319168152610ee4929190600401612d08565b6020604051808303818588803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610f3691906127d1565b50876001600160a01b0316631cff79cd73cd47e74a717b882efb54a3e17b59a5b1e31fd3c38c8e6000015189604051602401610f7493929190612c58565b60408051601f198184030181529181526020820180516001600160e01b0316636ce5768960e11b1790525160e084901b6001600160e01b0319168152610fbe929190600401612d08565b602060405180830381600087803b158015610fd857600080fd5b505af1158015610fec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101091906127d1565b5061103f6040518060400160405280600b81526020016a416176655632526570617960a81b8152508c86611915565b5050505050505050505050565b61106c8363095ea7b360e01b846000604051602401610c77929190612d2c565b610cae8363095ea7b360e01b8484604051602401610c77929190612d48565b6040840151602085015185516001600160a01b039081169116146110b6576110b2856113d0565b9150505b6000826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110f157600080fd5b505afa158015611105573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111299190612644565b90506111ac856001600160a01b031663fca513a86040518163ffffffff1660e01b815260040160206040518083038186803b15801561116757600080fd5b505afa15801561117b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119f9190612644565b8383878a6020015161170b565b60208701519203916000906001600160a01b038116600080516020612f5d83398151915214806111fc575060208801516001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b156112195750829050600080516020612f5d833981519152611232565b6020880151611232906001600160a01b0316868661104c565b846001600160a01b0316631cff79cd8373cd47e74a717b882efb54a3e17b59a5b1e31fd3c38a858960405160240161126c93929190612c58565b60408051601f198184030181529181526020820180516001600160e01b0316638340f54960e01b1790525160e085901b6001600160e01b03191681526112b6929190600401612d08565b6020604051808303818588803b1580156112cf57600080fd5b505af11580156112e3573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061130891906127d1565b506113376040518060400160405280600b81526020016a10585d99558c909bdbdcdd60aa1b8152508986611915565b5050505050505050565b6060611396826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166119c39092919063ffffffff16565b805190915015610cae57808060200190518101906113b49190612788565b610cae5760405162461bcd60e51b815260040161084390612deb565b6000806000806000600080516020612f5d8339815191526001600160a01b031686600001516001600160a01b0316141561148557855161140f906119da565b6001600160a01b031686526040808701518151630d0e30db60e41b8152915173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29263d0e30db09291600480830192600092919082900301818588803b15801561146b57600080fd5b505af115801561147f573d6000803e3d6000fd5b50505050505b6114a186604001518760c0015188600001518960a00151611a1b565b60408701805191909103905261012086015160600151156114de576114c7866000611c68565b9250905080156114de578561012001516020015192505b806114f8576114ee866000611e66565b91508560e0015192505b600061151773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26120af565b11156115fd576040516370a0823160e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d9082906370a082319061155c903090600401612bfb565b602060405180830381600087803b15801561157657600080fd5b505af115801561158a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ae91906127d1565b6040518263ffffffff1660e01b81526004016115ca9190612eb2565b600060405180830381600087803b1580156115e457600080fd5b505af11580156115f8573d6000803e3d6000fd5b505050505b60208601516001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561169a5761163886608001518760400151612153565b61164f600080516020612f5d8339815191526120af565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b815250906116945760405162461bcd60e51b81526004016108439190612d6c565b50611700565b6116ac86608001518760400151612153565b6116b987602001516120af565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b815250906116fe5760405162461bcd60e51b81526004016108439190612d6c565b505b509092509050915091565b60008261171a5750600061190c565b60006001600160a01b038316600080516020612f5d833981519152146117405782611756565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b90506000876001600160a01b031663b3596f07836040518263ffffffff1660e01b81526004016117869190612bfb565b60206040518083038186803b15801561179e57600080fd5b505afa1580156117b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d691906127d1565b90506117e18461218c565b601203600a0a6117f186836121ee565b816117f857fe5b04945084925060058704831115611810576005870492505b60007339c4a92dc506300c3ea4c67ca4ca611102ee6f2a6001600160a01b031663b38779eb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561185f57600080fd5b505afa158015611873573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118979190612644565b90506001600160a01b038516600080516020612f5d83398151915214156118f4576040516001600160a01b0382169085156108fc029086906000818181858888f193505050501580156118ee573d6000803e3d6000fd5b50611908565b6119086001600160a01b0386168286610c58565b5050505b95945050505050565b735c55b921f590a89c1ebe84df170e655a82b621266001600160a01b031663d061ce503033868660000151876020015188604001518860405160200161195e9493929190612caf565b6040516020818303038152906040526040518563ffffffff1660e01b815260040161198c9493929190612c0f565b600060405180830381600087803b1580156119a657600080fd5b505af11580156119ba573d6000803e3d6000fd5b50505050505050565b60606119d2848460008561220e565b949350505050565b60006001600160a01b038216600080516020612f5d83398151915214611a005781610b35565b5073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2919050565b60008115801590611aae5750604051632cdc77ab60e21b8152731b14e8d511c9a4395425314f849bd737baf8208f9063b371deac90611a5e908790600401612bfb565b60206040518083038186803b158015611a7657600080fd5b505afa158015611a8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aae9190612788565b15611b3d57604051636eeb543160e01b8152731b14e8d511c9a4395425314f849bd737baf8208f90636eeb543190611aea908790600401612bfb565b60206040518083038186803b158015611b0257600080fd5b505afa158015611b16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3a91906127d1565b91505b81611b4a575060006119d2565b818581611b5357fe5b049050600a8504811115611b675750600a84045b60007339c4a92dc506300c3ea4c67ca4ca611102ee6f2a6001600160a01b031663b38779eb6040518163ffffffff1660e01b815260040160206040518083038186803b158015611bb657600080fd5b505afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee9190612644565b90506001600160a01b038416600080516020612f5d8339815191521415611c4b576040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015611c45573d6000803e3d6000fd5b50611c5f565b611c5f6001600160a01b0385168284610c58565b50949350505050565b610120820151602001516040516302f5cc7960e11b81526000918291734ba1f38427b33b8ab7bb0490200dae1f1c36823f916305eb98f291611cad9190600401612bfb565b60206040518083038186803b158015611cc557600080fd5b505afa158015611cd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cfd9190612788565b611d0c57506000905080611e5f565b6101208401515160405163e0aa279760e01b81527325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d9163e0aa279791611d499190600401612bfb565b60206040518083038186803b158015611d6157600080fd5b505afa158015611d75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d999190612788565b611da857506000905080611e5f565b6101208401515160408501518551611dcb926001600160a01b0390911691610c58565b610120840151805160809091015160405163097396a160e31b81526001600160a01b0390921691634b9cb5089190611e099088908890600401612e77565b60408051808303818588803b158015611e2157600080fd5b505af1158015611e35573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e5a91906127a4565b915091505b9250929050565b60e082015160405163e0aa279760e01b81526000917325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d9163e0aa279791611ea391600401612bfb565b60206040518083038186803b158015611ebb57600080fd5b505afa158015611ecf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef39190612788565b6040518060400160405280600f81526020016e15dc985c1c195c881a5b9d985b1a59608a1b81525090611f395760405162461bcd60e51b81526004016108439190612d6c565b5060e083015160408401518451611f5b926001600160a01b0390911691610c58565b6000826001811115611f6957fe5b141561200f578260e001516001600160a01b0316635b6f36fc8460000151856020015186604001518761010001516040518563ffffffff1660e01b8152600401611fb69493929190612c7c565b602060405180830381600087803b158015611fd057600080fd5b505af1158015611fe4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200891906127d1565b9050610b35565b8260e001516001600160a01b0316633924db668460000151856020015186606001518761010001516040518563ffffffff1660e01b81526004016120569493929190612c7c565b602060405180830381600087803b15801561207057600080fd5b505af1158015612084573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a891906127d1565b9392505050565b60006001600160a01b038216600080516020612f5d83398151915214156120d757504761056d565b6040516370a0823160e01b81526001600160a01b038316906370a0823190612103903090600401612bfb565b60206040518083038186803b15801561211b57600080fd5b505afa15801561212f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3591906127d1565b6000670de0b6b3a764000061217d61216b85856122d2565b6002670de0b6b3a76400005b046122f6565b8161218457fe5b049392505050565b60006001600160a01b038216600080516020612f5d83398151915214156121b55750601261056d565b816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561211b57600080fd5b60008161217d61220685670de0b6b3a76400006122d2565b600285612177565b606061221985612306565b6122355760405162461bcd60e51b815260040161084390612db4565b60006060866001600160a01b031685876040516122529190612bdf565b60006040518083038185875af1925050503d806000811461228f576040519150601f19603f3d011682016040523d82523d6000602084013e612294565b606091505b509150915081156122a85791506119d29050565b8051156122b85780518082602001fd5b8360405162461bcd60e51b81526004016108439190612d6c565b60008115806122ed575050808202828282816122ea57fe5b04145b610b3557600080fd5b80820182811015610b3557600080fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906119d2575050151592915050565b60405180610140016040528060006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016123b66123bb565b905290565b6040518060c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001606081525090565b8035610b3581612f36565b8051610b3581612f36565b60008083601f840112612433578182fd5b50813567ffffffffffffffff81111561244a578182fd5b6020830191508360208083028501011115611e5f57600080fd5b600082601f830112612474578081fd5b813561248761248282612ee2565b612ebb565b915080825283602082850101111561249e57600080fd5b8060208401602084013760009082016020015292915050565b600082601f8301126124c7578081fd5b81516124d561248282612ee2565b91508082528360208285010111156124ec57600080fd5b6124fd816020840160208601612f06565b5092915050565b600060c08284031215612515578081fd5b61251f60c0612ebb565b9050813561252c81612f36565b8152602082013561253c81612f36565b6020820152604082013561254f81612f36565b80604083015250606082013560608201526080820135608082015260a082013567ffffffffffffffff81111561258457600080fd5b61259084828501612464565b60a08301525092915050565b600060c082840312156125ad578081fd5b6125b760c0612ebb565b905081516125c481612f36565b815260208201516125d481612f36565b602082015260408201516125e781612f36565b80604083015250606082015160608201526080820151608082015260a082015167ffffffffffffffff81111561261c57600080fd5b612590848285016124b7565b600060208284031215612639578081fd5b81356120a881612f36565b600060208284031215612655578081fd5b81516120a881612f36565b60008060408385031215612672578081fd5b823561267d81612f36565b946020939093013593505050565b600080600080600080600080600060a08a8c0312156126a8578485fd5b893567ffffffffffffffff808211156126bf578687fd5b6126cb8d838e01612422565b909b50995060208c01359150808211156126e3578687fd5b6126ef8d838e01612422565b909950975060408c0135915080821115612707578687fd5b6127138d838e01612422565b909750955060608c0135915061272882612f36565b90935060808b0135908082111561273d578384fd5b818c0191508c601f830112612750578384fd5b81358181111561275e578485fd5b8d602082850101111561276f578485fd5b6020830194508093505050509295985092959850929598565b600060208284031215612799578081fd5b81516120a881612f4e565b600080604083850312156127b6578182fd5b82516127c181612f4e565b6020939093015192949293505050565b6000602082840312156127e2578081fd5b5051919050565b6000602082840312156127fa578081fd5b813567ffffffffffffffff811115612810578182fd5b6119d284828501612464565b60008060008060008060c08789031215612834578384fd5b863567ffffffffffffffff81111561284a578485fd5b61285689828a01612464565b965050602087013561286781612f36565b94506040870135935060608701359250608087013561288581612f4e565b915060a087013561289581612f36565b809150509295509295509295565b6000602082840312156128b4578081fd5b813567ffffffffffffffff808211156128cb578283fd5b81840191506101408083870312156128e1578384fd5b6128ea81612ebb565b90506128f6868461240c565b8152612905866020850161240c565b602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015261293f8660c0850161240c565b60c08201526129518660e0850161240c565b60e08201526101008084013583811115612969578586fd5b61297588828701612464565b828401525050610120808401358381111561298e578586fd5b61299a88828701612504565b918301919091525095945050505050565b6000602082840312156129bc578081fd5b815167ffffffffffffffff808211156129d3578283fd5b81840191506101408083870312156129e9578384fd5b6129f281612ebb565b90506129fe8684612417565b8152612a0d8660208501612417565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a0820152612a478660c08501612417565b60c0820152612a598660e08501612417565b60e08201526101008084015183811115612a71578586fd5b612a7d888287016124b7565b8284015250506101208084015183811115612a96578586fd5b61299a8882870161259c565b6001600160a01b03169052565b60008151808452612ac7816020860160208601612f06565b601f01601f19169290920160200192915050565b6000610140612aeb848451612aa2565b6020830151612afd6020860182612aa2565b5060408301516040850152606083015160608501526080830151608085015260a083015160a085015260c0830151612b3860c0860182612aa2565b5060e0830151612b4b60e0860182612aa2565b50610100808401518282870152612b6483870182612aaf565b925050506101208084015185830382870152612b808382612b8a565b9695505050505050565b600060018060a01b0380835116845280602084015116602085015280604084015116604085015250606082015160608401526080820151608084015260a082015160c060a08501526119d260c0850182612aaf565b60008251612bf1818460208701612f06565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03858116825284166020820152608060408201819052600090612c3b90830185612aaf565b8281036060840152612c4d8185612aaf565b979650505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612b8090830184612aaf565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b039586168152938516602085015260408401929092526060830152909116608082015260a00190565b6001600160a01b03831681526040602082018190526000906119d290830184612aaf565b6001600160a01b0392909216825260ff16602082015260400190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6000602082526120a86020830184612aaf565b6020808252818101527f43616c6c6261636b73206f6e6c7920616c6c6f7765642066726f6d2041617665604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b602080825260159082015274696e69746961746f722069736e27742070726f787960581b604082015260600190565b6000602082526120a86020830184612adb565b600060408252612e8a6040830185612adb565b905060028310612e9657fe5b8260208301529392505050565b61ffff91909116815260200190565b90815260200190565b60405181810167ffffffffffffffff81118282101715612eda57600080fd5b604052919050565b600067ffffffffffffffff821115612ef8578081fd5b50601f01601f191660200190565b60005b83811015612f21578181015183820152602001612f09565b83811115612f30576000848401525b50505050565b6001600160a01b0381168114612f4b57600080fd5b50565b8015158114612f4b57600080fdfe000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeea2646970667358221220d79495ce7deb52c0fc52ebee1eb936a1badeaa63ceb9a86b5ddf814bc295231764736f6c634300060c0033
Deployed Bytecode
0x6080604052600436106101fd5760003560e01c80637b925ab11161010d578063a46a66c9116100a0578063c50ebaf81161006f578063c50ebaf8146104b1578063cc694d48146104c6578063d4f922dc146104db578063deca5f88146104f0578063f851a4401461051057610204565b8063a46a66c9146103b9578063a7304bf714610467578063ae08fd1014610487578063b13cdb201461049c57610204565b80638da5cb5b116100dc5780638da5cb5b146103f8578063920f5c841461040d578063a342f2381461037a578063a3b8e5d11461043a57610204565b80637b925ab1146103b957806381b9428014610209578063870e44d9146103ce5780638c8a7958146103e357610204565b8063314b633211610190578063449b9ffa1161015f578063449b9ffa14610365578063469048401461037a5780634d2ab9dc1461038f578063526d6461146103a45780637753f47b146102dc57610204565b8063314b63321461030657806339df18781461031b5780633a1283221461033057806341c0e1b51461035057610204565b80631e48907b116101cc5780631e48907b146102a5578063278d5831146102c757806329f7fc9e146102dc5780632ba38bcb146102f157610204565b8063040141e51461020957806304c9805c1461023457806305a363de1461025657806308d4f52a1461027857610204565b3661020457005b600080fd5b34801561021557600080fd5b5061021e610525565b60405161022b9190612bfb565b60405180910390f35b34801561024057600080fd5b5061024961053d565b60405161022b9190612eb2565b34801561026257600080fd5b5061026b610543565b60405161022b9190612ea3565b34801561028457600080fd5b506102986102933660046128a3565b610548565b60405161022b9190612d6c565b3480156102b157600080fd5b506102c56102c0366004612628565b610572565b005b3480156102d357600080fd5b506102986105ab565b3480156102e857600080fd5b5061021e6105d3565b3480156102fd57600080fd5b506102496105e5565b34801561031257600080fd5b5061021e6105ea565b34801561032757600080fd5b5061021e610602565b34801561033c57600080fd5b506102c561034b366004612660565b61061a565b34801561035c57600080fd5b506102c56106ad565b34801561037157600080fd5b506102986106d2565b34801561038657600080fd5b5061021e610704565b34801561039b57600080fd5b5061024961071c565b3480156103b057600080fd5b5061021e610722565b3480156103c557600080fd5b5061021e61073a565b3480156103da57600080fd5b50610249610752565b3480156103ef57600080fd5b5061021e61075e565b34801561040457600080fd5b5061021e610776565b34801561041957600080fd5b5061042d61042836600461268b565b610785565b60405161022b9190612d61565b34801561044657600080fd5b5061045a6104553660046127e9565b610b19565b60405161022b9190612e64565b34801561047357600080fd5b506102c5610482366004612628565b610b3b565b34801561049357600080fd5b50610298610b74565b3480156104a857600080fd5b5061021e610ba5565b3480156104bd57600080fd5b50610298610bbd565b3480156104d257600080fd5b50610298610bec565b3480156104e757600080fd5b50610249610c17565b3480156104fc57600080fd5b506102c561050b366004612628565b610c1c565b34801561051c57600080fd5b5061021e610c49565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b61014d81565b604081565b60608160405160200161055b9190612e64565b60405160208183030381529060405290505b919050565b6001546001600160a01b0316331461058957600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525081565b600080516020612f5d83398151915281565b600181565b7325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d81565b735c55b921f590a89c1ebe84df170e655a82b6212681565b6000546001600160a01b0316331461063157600080fd5b600080516020612f5d8339815191526001600160a01b038316141561068f57600080546040516001600160a01b039091169183156108fc02918491818181858888f19350505050158015610689573d6000803e3d6000fd5b506106a9565b6000546106a9906001600160a01b03848116911683610c58565b5050565b6000546001600160a01b031633146106c457600080fd5b6000546001600160a01b0316ff5b6040518060400160405280601681526020017516995c9bde08195e18da185b99d9481a5b9d985b1a5960521b81525081565b7339c4a92dc506300c3ea4c67ca4ca611102ee6f2a81565b61019081565b73637726f8b08a7abe3ae3acab01a80e2d8ddef77b81565b731b14e8d511c9a4395425314f849bd737baf8208f81565b670dbd2fc137a3000081565b734ba1f38427b33b8ab7bb0490200dae1f1c36823f81565b6000546001600160a01b031681565b60006060818080808061079a888a018a61281c565b9550955095509550955095506000856001600160a01b0316630261bf8b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156107e157600080fd5b505afa1580156107f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108199190612644565b9050336001600160a01b0382161461084c5760405162461bcd60e51b815260040161084390612d7f565b60405180910390fd5b816001600160a01b03168b6001600160a01b03161461087d5760405162461bcd60e51b815260040161084390612e35565b61088561233f565b61088e88610b19565b9050826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108c957600080fd5b505afa1580156108dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109019190612644565b6001600160a01b031660c082015261019060a08201526040516320eb73ed60e11b815273637726f8b08a7abe3ae3acab01a80e2d8ddef77b906341d6e7da9061094e903290600401612bfb565b60206040518083038186803b15801561096657600080fd5b505afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190612788565b156109ac5761014d60a08201525b60008e8e60008181106109bb57fe5b90506020020135905060008183604001510190508515610ac5576109e3838a8a888b87610cb3565b82516001600160a01b038116600080516020612f5d8339815191521480610a2657506001600160a01b03811673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b15610aab5773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b505050505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290505b610abf6001600160a01b038216868461104c565b50610ad1565b610ad1838a8a8861108b565b60405132904780156108fc02916000818181858888f19350505050158015610afd573d6000803e3d6000fd5b5060019a50505050505050505050509998505050505050505050565b610b2161233f565b81806020019051810190610b3591906129ab565b92915050565b6001546001600160a01b03163314610b5257600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6040518060400160405280601581526020017413d99998da185a5b8819185d18481a5b9d985b1a59605a1b81525081565b73cd47e74a717b882efb54a3e17b59a5b1e31fd3c381565b604051806040016040528060138152602001724465737420616d6f756e74206d697373696e6760681b81525081565b6040518060400160405280600f81526020016e15dc985c1c195c881a5b9d985b1a59608a1b81525081565b600281565b6000546001600160a01b03163314610c3357600080fd5b6001546001600160a01b031615610b5257600080fd5b6001546001600160a01b031681565b610cae8363a9059cbb60e01b8484604051602401610c77929190612d48565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611341565b505050565b60408601805182810391829052602088015188519192916001600160a01b03908116911614610ce957610ce5886113d0565b9150505b6000856001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d2457600080fd5b505afa158015610d38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5c9190612644565b9050610ddf886001600160a01b031663fca513a86040518163ffffffff1660e01b815260040160206040518083038186803b158015610d9a57600080fd5b505afa158015610dae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd29190612644565b83838a8d6020015161170b565b60208a015192039147906000906001600160a01b0316600080516020612f5d8339815191521480610e30575060208b01516001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b15610e3f575082900382610e58565b60208b0151610e58906001600160a01b0316898661104c565b876001600160a01b0316631cff79cd8273cd47e74a717b882efb54a3e17b59a5b1e31fd3c38d8f60200151898d8a604051602401610e9a959493929190612cd8565b60408051601f198184030181529181526020820180516001600160e01b0316632c6951f360e21b1790525160e085901b6001600160e01b0319168152610ee4929190600401612d08565b6020604051808303818588803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610f3691906127d1565b50876001600160a01b0316631cff79cd73cd47e74a717b882efb54a3e17b59a5b1e31fd3c38c8e6000015189604051602401610f7493929190612c58565b60408051601f198184030181529181526020820180516001600160e01b0316636ce5768960e11b1790525160e084901b6001600160e01b0319168152610fbe929190600401612d08565b602060405180830381600087803b158015610fd857600080fd5b505af1158015610fec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101091906127d1565b5061103f6040518060400160405280600b81526020016a416176655632526570617960a81b8152508c86611915565b5050505050505050505050565b61106c8363095ea7b360e01b846000604051602401610c77929190612d2c565b610cae8363095ea7b360e01b8484604051602401610c77929190612d48565b6040840151602085015185516001600160a01b039081169116146110b6576110b2856113d0565b9150505b6000826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110f157600080fd5b505afa158015611105573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111299190612644565b90506111ac856001600160a01b031663fca513a86040518163ffffffff1660e01b815260040160206040518083038186803b15801561116757600080fd5b505afa15801561117b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119f9190612644565b8383878a6020015161170b565b60208701519203916000906001600160a01b038116600080516020612f5d83398151915214806111fc575060208801516001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b156112195750829050600080516020612f5d833981519152611232565b6020880151611232906001600160a01b0316868661104c565b846001600160a01b0316631cff79cd8373cd47e74a717b882efb54a3e17b59a5b1e31fd3c38a858960405160240161126c93929190612c58565b60408051601f198184030181529181526020820180516001600160e01b0316638340f54960e01b1790525160e085901b6001600160e01b03191681526112b6929190600401612d08565b6020604051808303818588803b1580156112cf57600080fd5b505af11580156112e3573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061130891906127d1565b506113376040518060400160405280600b81526020016a10585d99558c909bdbdcdd60aa1b8152508986611915565b5050505050505050565b6060611396826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166119c39092919063ffffffff16565b805190915015610cae57808060200190518101906113b49190612788565b610cae5760405162461bcd60e51b815260040161084390612deb565b6000806000806000600080516020612f5d8339815191526001600160a01b031686600001516001600160a01b0316141561148557855161140f906119da565b6001600160a01b031686526040808701518151630d0e30db60e41b8152915173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29263d0e30db09291600480830192600092919082900301818588803b15801561146b57600080fd5b505af115801561147f573d6000803e3d6000fd5b50505050505b6114a186604001518760c0015188600001518960a00151611a1b565b60408701805191909103905261012086015160600151156114de576114c7866000611c68565b9250905080156114de578561012001516020015192505b806114f8576114ee866000611e66565b91508560e0015192505b600061151773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26120af565b11156115fd576040516370a0823160e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d9082906370a082319061155c903090600401612bfb565b602060405180830381600087803b15801561157657600080fd5b505af115801561158a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ae91906127d1565b6040518263ffffffff1660e01b81526004016115ca9190612eb2565b600060405180830381600087803b1580156115e457600080fd5b505af11580156115f8573d6000803e3d6000fd5b505050505b60208601516001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561169a5761163886608001518760400151612153565b61164f600080516020612f5d8339815191526120af565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b815250906116945760405162461bcd60e51b81526004016108439190612d6c565b50611700565b6116ac86608001518760400151612153565b6116b987602001516120af565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b815250906116fe5760405162461bcd60e51b81526004016108439190612d6c565b505b509092509050915091565b60008261171a5750600061190c565b60006001600160a01b038316600080516020612f5d833981519152146117405782611756565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b90506000876001600160a01b031663b3596f07836040518263ffffffff1660e01b81526004016117869190612bfb565b60206040518083038186803b15801561179e57600080fd5b505afa1580156117b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d691906127d1565b90506117e18461218c565b601203600a0a6117f186836121ee565b816117f857fe5b04945084925060058704831115611810576005870492505b60007339c4a92dc506300c3ea4c67ca4ca611102ee6f2a6001600160a01b031663b38779eb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561185f57600080fd5b505afa158015611873573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118979190612644565b90506001600160a01b038516600080516020612f5d83398151915214156118f4576040516001600160a01b0382169085156108fc029086906000818181858888f193505050501580156118ee573d6000803e3d6000fd5b50611908565b6119086001600160a01b0386168286610c58565b5050505b95945050505050565b735c55b921f590a89c1ebe84df170e655a82b621266001600160a01b031663d061ce503033868660000151876020015188604001518860405160200161195e9493929190612caf565b6040516020818303038152906040526040518563ffffffff1660e01b815260040161198c9493929190612c0f565b600060405180830381600087803b1580156119a657600080fd5b505af11580156119ba573d6000803e3d6000fd5b50505050505050565b60606119d2848460008561220e565b949350505050565b60006001600160a01b038216600080516020612f5d83398151915214611a005781610b35565b5073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2919050565b60008115801590611aae5750604051632cdc77ab60e21b8152731b14e8d511c9a4395425314f849bd737baf8208f9063b371deac90611a5e908790600401612bfb565b60206040518083038186803b158015611a7657600080fd5b505afa158015611a8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aae9190612788565b15611b3d57604051636eeb543160e01b8152731b14e8d511c9a4395425314f849bd737baf8208f90636eeb543190611aea908790600401612bfb565b60206040518083038186803b158015611b0257600080fd5b505afa158015611b16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3a91906127d1565b91505b81611b4a575060006119d2565b818581611b5357fe5b049050600a8504811115611b675750600a84045b60007339c4a92dc506300c3ea4c67ca4ca611102ee6f2a6001600160a01b031663b38779eb6040518163ffffffff1660e01b815260040160206040518083038186803b158015611bb657600080fd5b505afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee9190612644565b90506001600160a01b038416600080516020612f5d8339815191521415611c4b576040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015611c45573d6000803e3d6000fd5b50611c5f565b611c5f6001600160a01b0385168284610c58565b50949350505050565b610120820151602001516040516302f5cc7960e11b81526000918291734ba1f38427b33b8ab7bb0490200dae1f1c36823f916305eb98f291611cad9190600401612bfb565b60206040518083038186803b158015611cc557600080fd5b505afa158015611cd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cfd9190612788565b611d0c57506000905080611e5f565b6101208401515160405163e0aa279760e01b81527325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d9163e0aa279791611d499190600401612bfb565b60206040518083038186803b158015611d6157600080fd5b505afa158015611d75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d999190612788565b611da857506000905080611e5f565b6101208401515160408501518551611dcb926001600160a01b0390911691610c58565b610120840151805160809091015160405163097396a160e31b81526001600160a01b0390921691634b9cb5089190611e099088908890600401612e77565b60408051808303818588803b158015611e2157600080fd5b505af1158015611e35573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e5a91906127a4565b915091505b9250929050565b60e082015160405163e0aa279760e01b81526000917325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d9163e0aa279791611ea391600401612bfb565b60206040518083038186803b158015611ebb57600080fd5b505afa158015611ecf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef39190612788565b6040518060400160405280600f81526020016e15dc985c1c195c881a5b9d985b1a59608a1b81525090611f395760405162461bcd60e51b81526004016108439190612d6c565b5060e083015160408401518451611f5b926001600160a01b0390911691610c58565b6000826001811115611f6957fe5b141561200f578260e001516001600160a01b0316635b6f36fc8460000151856020015186604001518761010001516040518563ffffffff1660e01b8152600401611fb69493929190612c7c565b602060405180830381600087803b158015611fd057600080fd5b505af1158015611fe4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200891906127d1565b9050610b35565b8260e001516001600160a01b0316633924db668460000151856020015186606001518761010001516040518563ffffffff1660e01b81526004016120569493929190612c7c565b602060405180830381600087803b15801561207057600080fd5b505af1158015612084573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a891906127d1565b9392505050565b60006001600160a01b038216600080516020612f5d83398151915214156120d757504761056d565b6040516370a0823160e01b81526001600160a01b038316906370a0823190612103903090600401612bfb565b60206040518083038186803b15801561211b57600080fd5b505afa15801561212f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3591906127d1565b6000670de0b6b3a764000061217d61216b85856122d2565b6002670de0b6b3a76400005b046122f6565b8161218457fe5b049392505050565b60006001600160a01b038216600080516020612f5d83398151915214156121b55750601261056d565b816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561211b57600080fd5b60008161217d61220685670de0b6b3a76400006122d2565b600285612177565b606061221985612306565b6122355760405162461bcd60e51b815260040161084390612db4565b60006060866001600160a01b031685876040516122529190612bdf565b60006040518083038185875af1925050503d806000811461228f576040519150601f19603f3d011682016040523d82523d6000602084013e612294565b606091505b509150915081156122a85791506119d29050565b8051156122b85780518082602001fd5b8360405162461bcd60e51b81526004016108439190612d6c565b60008115806122ed575050808202828282816122ea57fe5b04145b610b3557600080fd5b80820182811015610b3557600080fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906119d2575050151592915050565b60405180610140016040528060006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016123b66123bb565b905290565b6040518060c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001606081525090565b8035610b3581612f36565b8051610b3581612f36565b60008083601f840112612433578182fd5b50813567ffffffffffffffff81111561244a578182fd5b6020830191508360208083028501011115611e5f57600080fd5b600082601f830112612474578081fd5b813561248761248282612ee2565b612ebb565b915080825283602082850101111561249e57600080fd5b8060208401602084013760009082016020015292915050565b600082601f8301126124c7578081fd5b81516124d561248282612ee2565b91508082528360208285010111156124ec57600080fd5b6124fd816020840160208601612f06565b5092915050565b600060c08284031215612515578081fd5b61251f60c0612ebb565b9050813561252c81612f36565b8152602082013561253c81612f36565b6020820152604082013561254f81612f36565b80604083015250606082013560608201526080820135608082015260a082013567ffffffffffffffff81111561258457600080fd5b61259084828501612464565b60a08301525092915050565b600060c082840312156125ad578081fd5b6125b760c0612ebb565b905081516125c481612f36565b815260208201516125d481612f36565b602082015260408201516125e781612f36565b80604083015250606082015160608201526080820151608082015260a082015167ffffffffffffffff81111561261c57600080fd5b612590848285016124b7565b600060208284031215612639578081fd5b81356120a881612f36565b600060208284031215612655578081fd5b81516120a881612f36565b60008060408385031215612672578081fd5b823561267d81612f36565b946020939093013593505050565b600080600080600080600080600060a08a8c0312156126a8578485fd5b893567ffffffffffffffff808211156126bf578687fd5b6126cb8d838e01612422565b909b50995060208c01359150808211156126e3578687fd5b6126ef8d838e01612422565b909950975060408c0135915080821115612707578687fd5b6127138d838e01612422565b909750955060608c0135915061272882612f36565b90935060808b0135908082111561273d578384fd5b818c0191508c601f830112612750578384fd5b81358181111561275e578485fd5b8d602082850101111561276f578485fd5b6020830194508093505050509295985092959850929598565b600060208284031215612799578081fd5b81516120a881612f4e565b600080604083850312156127b6578182fd5b82516127c181612f4e565b6020939093015192949293505050565b6000602082840312156127e2578081fd5b5051919050565b6000602082840312156127fa578081fd5b813567ffffffffffffffff811115612810578182fd5b6119d284828501612464565b60008060008060008060c08789031215612834578384fd5b863567ffffffffffffffff81111561284a578485fd5b61285689828a01612464565b965050602087013561286781612f36565b94506040870135935060608701359250608087013561288581612f4e565b915060a087013561289581612f36565b809150509295509295509295565b6000602082840312156128b4578081fd5b813567ffffffffffffffff808211156128cb578283fd5b81840191506101408083870312156128e1578384fd5b6128ea81612ebb565b90506128f6868461240c565b8152612905866020850161240c565b602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015261293f8660c0850161240c565b60c08201526129518660e0850161240c565b60e08201526101008084013583811115612969578586fd5b61297588828701612464565b828401525050610120808401358381111561298e578586fd5b61299a88828701612504565b918301919091525095945050505050565b6000602082840312156129bc578081fd5b815167ffffffffffffffff808211156129d3578283fd5b81840191506101408083870312156129e9578384fd5b6129f281612ebb565b90506129fe8684612417565b8152612a0d8660208501612417565b602082015260408301516040820152606083015160608201526080830151608082015260a083015160a0820152612a478660c08501612417565b60c0820152612a598660e08501612417565b60e08201526101008084015183811115612a71578586fd5b612a7d888287016124b7565b8284015250506101208084015183811115612a96578586fd5b61299a8882870161259c565b6001600160a01b03169052565b60008151808452612ac7816020860160208601612f06565b601f01601f19169290920160200192915050565b6000610140612aeb848451612aa2565b6020830151612afd6020860182612aa2565b5060408301516040850152606083015160608501526080830151608085015260a083015160a085015260c0830151612b3860c0860182612aa2565b5060e0830151612b4b60e0860182612aa2565b50610100808401518282870152612b6483870182612aaf565b925050506101208084015185830382870152612b808382612b8a565b9695505050505050565b600060018060a01b0380835116845280602084015116602085015280604084015116604085015250606082015160608401526080820151608084015260a082015160c060a08501526119d260c0850182612aaf565b60008251612bf1818460208701612f06565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03858116825284166020820152608060408201819052600090612c3b90830185612aaf565b8281036060840152612c4d8185612aaf565b979650505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612b8090830184612aaf565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b039586168152938516602085015260408401929092526060830152909116608082015260a00190565b6001600160a01b03831681526040602082018190526000906119d290830184612aaf565b6001600160a01b0392909216825260ff16602082015260400190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6000602082526120a86020830184612aaf565b6020808252818101527f43616c6c6261636b73206f6e6c7920616c6c6f7765642066726f6d2041617665604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b602080825260159082015274696e69746961746f722069736e27742070726f787960581b604082015260600190565b6000602082526120a86020830184612adb565b600060408252612e8a6040830185612adb565b905060028310612e9657fe5b8260208301529392505050565b61ffff91909116815260200190565b90815260200190565b60405181810167ffffffffffffffff81118282101715612eda57600080fd5b604052919050565b600067ffffffffffffffff821115612ef8578081fd5b50601f01601f191660200190565b60005b83811015612f21578181015183820152602001612f09565b83811115612f30576000848401525b50505050565b6001600160a01b0381168114612f4b57600080fd5b50565b8015158114612f4b57600080fdfe000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeea2646970667358221220d79495ce7deb52c0fc52ebee1eb936a1badeaa63ceb9a86b5ddf814bc295231764736f6c634300060c0033
Deployed Bytecode Sourcemap
59227:7082:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40998:81;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41164:48;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;41484:46::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;47540:134::-;;;;;;;;;;-1:-1:-1;47540:134:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;39546:122::-;;;;;;;;;;-1:-1:-1;39546:122:0;;;;;:::i;:::-;;:::i;:::-;;52676:56;;;;;;;;;;;;;:::i;47999:86::-;;;;;;;;;;;;;:::i;41539:34::-;;;;;;;;;;;;;:::i;48395:92::-;;;;;;;;;;;;;:::i;59342:85::-;;;;;;;;;;;;;:::i;39841:285::-;;;;;;;;;;-1:-1:-1;39841:285:0;;;;;:::i;:::-;;:::i;39714:80::-;;;;;;;;;;;;;:::i;52885:72::-;;;;;;;;;;;;;:::i;40798:102::-;;;;;;;;;;;;;:::i;41099:45::-;;;;;;;;;;;;;:::i;41233:89::-;;;;;;;;;;;;;:::i;40909:82::-;;;;;;;;;;;;;:::i;41412:65::-;;;;;;;;;;;;;:::i;48496:87::-;;;;;;;;;;;;;:::i;38472:20::-;;;;;;;;;;;;;:::i;63914:1927::-;;;;;;;;;;-1:-1:-1;63914:1927:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;47682:159::-;;;;;;;;;;-1:-1:-1;47682:159:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;39325:122::-;;;;;;;;;;-1:-1:-1;39325:122:0;;;;;:::i;:::-;;:::i;47882:74::-;;;;;;;;;;;;;:::i;59436:85::-;;;;;;;;;;;;;:::i;52739:70::-;;;;;;;;;;;;;:::i;52816:62::-;;;;;;;;;;;;;:::i;41580:36::-;;;;;;;;;;;;;:::i;39042:161::-;;;;;;;;;;-1:-1:-1;39042:161:0;;;;;:::i;:::-;;:::i;38499:20::-;;;;;;;;;;;;;:::i;40998:81::-;41037:42;40998:81;:::o;41164:48::-;41209:3;41164:48;:::o;41484:46::-;41528:2;41484:46;:::o;47540:134::-;47615:12;47658:7;47647:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;47640:26;;47540:134;;;;:::o;39546:122::-;39627:5;;-1:-1:-1;;;;;39627:5:0;39613:10;:19;39605:28;;;;;;39646:5;:14;;-1:-1:-1;;;;;;39646:14:0;-1:-1:-1;;;;;39646:14:0;;;;;;;;;;39546:122::o;52676:56::-;;;;;;;;;;;;;;-1:-1:-1;;;52676:56:0;;;;:::o;47999:86::-;-1:-1:-1;;;;;;;;;;;47999:86:0;:::o;41539:34::-;41572:1;41539:34;:::o;48395:92::-;48445:42;48395:92;:::o;59342:85::-;59385:42;59342:85;:::o;39841:285::-;38568:5;;-1:-1:-1;;;;;38568:5:0;38577:10;38568:19;38560:28;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;39931:52:0;::::1;;39927:192;;;40008:5;::::0;;40000:32:::1;::::0;-1:-1:-1;;;;;40008:5:0;;::::1;::::0;40000:32;::::1;;;::::0;40024:7;;40000:32;40008:5;40000:32;40024:7;40008:5;40000:32;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;39927:192;;;40092:5;::::0;40065:42:::1;::::0;-1:-1:-1;;;;;40065:26:0;;::::1;::::0;40092:5:::1;40099:7:::0;40065:26:::1;:42::i;:::-;39841:285:::0;;:::o;39714:80::-;38568:5;;-1:-1:-1;;;;;38568:5:0;38577:10;38568:19;38560:28;;;;;;39779:5:::1;::::0;-1:-1:-1;;;;;39779:5:0::1;39758:28;52885:72:::0;;;;;;;;;;;;;;-1:-1:-1;;;52885:72:0;;;;:::o;40798:102::-;40857:42;40798:102;:::o;41099:45::-;41141:3;41099:45;:::o;41233:89::-;41280:42;41233:89;:::o;40909:82::-;40949:42;40909:82;:::o;41412:65::-;41459:18;41412:65;:::o;48496:87::-;48541:42;48496:87;:::o;38472:20::-;;;-1:-1:-1;;;;;38472:20:0;;:::o;63914:1927::-;64127:4;64159:30;64127:4;;;;;64348:69;;;;64359:6;64348:69;:::i;:::-;64144:273;;;;;;;;;;;;64430:19;64484:6;-1:-1:-1;;;;;64452:54:0;;:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64430:78;-1:-1:-1;64529:10:0;-1:-1:-1;;;;;64529:25:0;;;64521:70;;;;-1:-1:-1;;;64521:70:0;;;;;;;:::i;:::-;;;;;;;;;64623:5;-1:-1:-1;;;;;64610:18:0;:9;-1:-1:-1;;;;;64610:18:0;;64602:52;;;;-1:-1:-1;;;64602:52:0;;;;;;;:::i;:::-;64667:26;;:::i;:::-;64696:37;64715:17;64696:18;:37::i;:::-;64667:66;;64765:5;-1:-1:-1;;;;;64758:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;64744:35:0;:11;;;:35;41141:3;64790:20;;;:41;64846:52;;-1:-1:-1;;;64846:52:0;;41280:42;;64846:41;;:52;;64888:9;;64846:52;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64842:129;;;41209:3;64915:20;;;:44;64842:129;65027:11;65041:8;;65050:1;65041:11;;;;;;;;;;;;;65027:25;;65063:26;65111:3;65092:6;:16;;;:22;65063:51;;65214:7;65210:546;;;65238:52;65244:6;65252;65260:7;65269:5;65276:8;65286:3;65238:5;:52::i;:::-;65323:14;;-1:-1:-1;;;;;65356:17:0;;-1:-1:-1;;;;;;;;;;;65356:17:0;;:42;;-1:-1:-1;;;;;;65377:21:0;;41037:42;65377:21;65356:42;65352:249;;;41037:42;-1:-1:-1;;;;;65482:36:0;;65525:18;65482:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41037:42;65565:20;;65352:249;65617:57;-1:-1:-1;;;;;65617:24:0;;65642:11;65655:18;65617:24;:57::i;:::-;65210:546;;;;65707:37;65713:6;65721;65729:7;65738:5;65707;:37::i;:::-;65768:41;;:9;;65787:21;65768:41;;;;;;;;;65787:21;65768:9;:41;;;;;;;;;;;;;;;;;;;;;65829:4;65822:11;;;;;;;;;;;;63914:1927;;;;;;;;;;;:::o;47682:159::-;47750:27;;:::i;:::-;47811:5;47800:33;;;;;;;;;;;;:::i;:::-;47790:43;47682:159;-1:-1:-1;;47682:159:0:o;39325:122::-;39406:5;;-1:-1:-1;;;;;39406:5:0;39392:10;:19;39384:28;;;;;;39425:5;:14;;-1:-1:-1;;;;;;39425:14:0;-1:-1:-1;;;;;39425:14:0;;;;;;;;;;39325:122::o;47882:74::-;;;;;;;;;;;;;;-1:-1:-1;;;47882:74:0;;;;:::o;59436:85::-;59479:42;59436:85;:::o;52739:70::-;;;;;;;;;;;;;;-1:-1:-1;;;52739:70:0;;;;:::o;52816:62::-;;;;;;;;;;;;;;-1:-1:-1;;;52816:62:0;;;;:::o;41580:36::-;41615:1;41580:36;:::o;39042:161::-;39123:5;;-1:-1:-1;;;;;39123:5:0;39109:10;:19;39101:28;;;;;;39148:5;;-1:-1:-1;;;;;39148:5:0;:19;39140:28;;;;;38499:20;;;-1:-1:-1;;;;;38499:20:0;;:::o;5643:176::-;5725:86;5745:5;5775:23;;;5800:2;5804:5;5752:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;5752:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;5752:58:0;-1:-1:-1;;;;;;5752:58:0;;;;;;;;;;5725:19;:86::i;:::-;5643:176;;;:::o;61170:2736::-;61507:23;;;;;61630:44;;;61604:70;;;;61819:22;;;;61794:21;;61507:23;;61630:44;-1:-1:-1;;;;;61794:47:0;;;;;;61790:120;;61878:20;61884:13;61878:5;:20::i;:::-;61858:40;-1:-1:-1;;61790:120:0;61922:12;61944:6;-1:-1:-1;;;;;61937:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;61922:37;;61987:200;62044:7;-1:-1:-1;;;;;62012:55:0;;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;62084:13;62112:4;62131:8;62154:13;:22;;;61987:10;:200::i;:::-;62657:22;;;;61970:217;;;62472:21;;62446:23;;-1:-1:-1;;;;;62657:34:0;-1:-1:-1;;;;;;;;;;;62657:34:0;;:76;;-1:-1:-1;62695:22:0;;;;-1:-1:-1;;;;;62695:38:0;41037:42;62695:38;62657:76;62653:277;;;-1:-1:-1;62750:32:0;;;62769:13;62653:277;;;62860:22;;;;62854:64;;-1:-1:-1;;;;;62854:41:0;62896:6;62904:13;62854:41;:64::i;:::-;63087:6;-1:-1:-1;;;;;63071:32:0;;63111:8;59479:42;63292:7;63318:13;:22;;;63359:13;63391:9;63419:4;63166:272;;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;63166:272:0;;;;;;;;;;;;;;-1:-1:-1;;;;;63166:272:0;-1:-1:-1;;;63166:272:0;;;63071:378;;;;;-1:-1:-1;;;;;;63071:378:0;;;;;;63166:272;63071:378;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;63567:6;-1:-1:-1;;;;;63551:32:0;;59479:42;63725:7;63751:13;:21;;;63791:15;63629:192;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;63629:192:0;;;;;;;;;;;;;;-1:-1:-1;;;;;63629:192:0;-1:-1:-1;;;63629:192:0;;;63551:281;;;;;-1:-1:-1;;;;;;63551:281:0;;;;;;63629:192;63551:281;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;63845:53;;;;;;;;;;;;;;-1:-1:-1;;;63845:53:0;;;63869:13;63884;63845:8;:53::i;:::-;61170:2736;;;;;;;;;;;:::o;6192:281::-;6278:86;6298:5;6328:22;;;6352:7;6361:1;6305:58;;;;;;;;;:::i;6278:86::-;6375:90;6395:5;6425:22;;;6449:7;6458:5;6402:62;;;;;;;;;:::i;59530:1632::-;59718:23;;;;59781:22;;;;59756:21;;-1:-1:-1;;;;;59756:47:0;;;;;;59752:120;;59840:20;59846:13;59840:5;:20::i;:::-;59820:40;-1:-1:-1;;59752:120:0;59884:12;59906:6;-1:-1:-1;;;;;59899:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59884:37;;59949:200;60006:7;-1:-1:-1;;;;;59974:55:0;;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60046:13;60074:4;60093:8;60116:13;:22;;;59949:10;:200::i;:::-;60325:22;;;;59932:217;;;60278:16;;-1:-1:-1;;;;;60493:34:0;;-1:-1:-1;;;;;;;;;;;60493:34:0;;:76;;-1:-1:-1;60531:22:0;;;;-1:-1:-1;;;;;60531:38:0;41037:42;60531:38;60493:76;60489:261;;;-1:-1:-1;60597:13:0;;-1:-1:-1;;;;;;;;;;;;60489:261:0;;;60680:22;;;;60674:64;;-1:-1:-1;;;;;60674:41:0;60716:6;60724:13;60674:41;:64::i;:::-;60825:6;-1:-1:-1;;;;;60809:32:0;;60849:8;59479:42;60999:7;61025:5;61049:13;60904:173;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;60904:173:0;;;;;;;;;;;;;;-1:-1:-1;;;;;60904:173:0;-1:-1:-1;;;60904:173:0;;;60809:279;;;;;-1:-1:-1;;;;;;60809:279:0;;;;;;60904:173;60809:279;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;61101:53;;;;;;;;;;;;;;-1:-1:-1;;;61101:53:0;;;61125:13;61140;61101:8;:53::i;:::-;59530:1632;;;;;;;;:::o;7112:419::-;7194:23;7220:69;7248:4;7220:69;;;;;;;;;;;;;;;;;7228:5;-1:-1:-1;;;;;7220:27:0;;;:69;;;;;:::i;:::-;7304:17;;7194:95;;-1:-1:-1;7304:21:0;7300:224;;7446:10;7435:30;;;;;;;;;;;;:::i;:::-;7427:85;;;;-1:-1:-1;;;7427:85:0;;;;;;;:::i;53228:1670::-;53289:7;53298:4;53317:15;53343:17;53371:12;-1:-1:-1;;;;;;;;;;;;;;;;53444:35:0;:6;:14;;;-1:-1:-1;;;;;53444:35:0;;53440:201;;;53527:14;;53513:29;;:13;:29::i;:::-;-1:-1:-1;;;;;53496:46:0;;;53610:16;;;;;53557:72;;-1:-1:-1;;;53557:72:0;;;;48140:42;;53557:45;;53610:16;53557:72;;;;;53496:14;;53557:72;;;;;;;53610:16;48140:42;53557:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53440:201;53673:75;53680:6;:16;;;53698:6;:11;;;53711:6;:14;;;53727:6;:20;;;53673:6;:75::i;:::-;53653:16;;;:95;;;;;;;;53828:19;;;;:25;;;:29;53824:228;;53900:34;53910:6;53918:15;53900:9;:34::i;:::-;53874:60;-1:-1:-1;53874:60:0;-1:-1:-1;53951:90:0;;;;53993:6;:19;;;:32;;;53983:42;;53951:90;54122:7;54117:129;;54161:34;54171:6;54179:15;54161:9;:34::i;:::-;54146:49;;54220:6;:14;;;54210:24;;54117:129;54362:1;54326:33;48140:42;54326:10;:33::i;:::-;:37;54322:212;;;54445:62;;-1:-1:-1;;;54445:62:0;;48140:42;;54380:46;;48140:42;;54445:47;;:62;;54501:4;;54445:62;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;54380:142;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54322:212;54550:15;;;;-1:-1:-1;;;;;54550:40:0;48140:42;54550:40;54546:302;;;54648:39;54653:6;:15;;;54670:6;:16;;;54648:4;:39::i;:::-;54615:29;-1:-1:-1;;;;;;;;;;;54615:10:0;:29::i;:::-;:72;;54689:16;;;;;;;;;;;;;-1:-1:-1;;;54689:16:0;;;54607:99;;;;;-1:-1:-1;;;54607:99:0;;;;;;;;:::i;:::-;;54546:302;;;54778:39;54783:6;:15;;;54800:6;:16;;;54778:4;:39::i;:::-;54747:27;54758:6;:15;;;54747:10;:27::i;:::-;:70;;54819:16;;;;;;;;;;;;;-1:-1:-1;;;54819:16:0;;;54739:97;;;;;-1:-1:-1;;;54739:97:0;;;;;;;;:::i;:::-;;54546:302;-1:-1:-1;54868:7:0;;-1:-1:-1;54877:12:0;-1:-1:-1;53228:1670:0;;;:::o;42041:1017::-;42167:12;42196:13;42192:27;;-1:-1:-1;42218:1:0;42211:8;;42192:27;42379:18;-1:-1:-1;;;;;42400:22:0;;-1:-1:-1;;;;;;;;;;;42400:22:0;:50;;42440:10;42400:50;;;41037:42;42400:50;42379:71;;42461:13;42500:14;-1:-1:-1;;;;;42477:52:0;;42530:10;42477:64;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42461:80;;42600:24;42613:10;42600:12;:24::i;:::-;42595:2;:29;42588:2;:37;42563:21;42568:8;42578:5;42563:4;:21::i;:::-;:63;;;;;;;-1:-1:-1;42563:63:0;;-1:-1:-1;42752:1:0;42742:7;:11;42731:7;:23;42727:77;;;42791:1;42781:7;:11;42771:21;;42727:77;42816:18;40857:42;-1:-1:-1;;;;;42837:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42816:46;-1:-1:-1;;;;;;42879:22:0;;-1:-1:-1;;;;;;;;;;;42879:22:0;42875:176;;;42918:37;;-1:-1:-1;;;;;42918:28:0;;;:37;;;;;42947:7;;42918:37;;;;42947:7;42918:28;:37;;;;;;;;;;;;;;;;;;;;;42875:176;;;42988:51;-1:-1:-1;;;;;42988:30:0;;43019:10;43031:7;42988:30;:51::i;:::-;42041:1017;;;;;;;;;;;:::o;65849:357::-;59385:42;-1:-1:-1;;;;;65964:37:0;;66024:4;66044:10;66069:5;66100:13;:21;;;66123:13;:22;;;66147:13;:23;;;66172:14;66089:98;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;65964:234;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65849:357;;;:::o;2034:196::-;2137:12;2169:53;2192:6;2200:4;2206:1;2209:12;2169:22;:53::i;:::-;2162:60;2034:196;-1:-1:-1;;;;2034:196:0:o;51569:151::-;51629:7;-1:-1:-1;;;;;51656:25:0;;-1:-1:-1;;;;;;;;;;;51656:25:0;:56;;51708:4;51656:56;;;-1:-1:-1;48140:42:0;;51569:151;-1:-1:-1;51569:151:0:o;49883:905::-;49989:17;50023:19;;;;;:71;;-1:-1:-1;50046:48:0;;-1:-1:-1;;;50046:48:0;;48346:42;;50046:41;;:48;;50088:5;;50046:48;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;50019:174;;;50128:53;;-1:-1:-1;;;50128:53:0;;48346:42;;50128:46;;:53;;50175:5;;50128:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;50111:70;;50019:174;50209:19;50205:576;;-1:-1:-1;50257:1:0;50205:576;;;50313:14;50303:7;:24;;;;;;;-1:-1:-1;50429:2:0;50419:7;:12;50406:9;:26;50402:91;;;-1:-1:-1;50475:2:0;50465:12;;50402:91;50509:18;48251:42;-1:-1:-1;;;;;50530:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;50509:47;-1:-1:-1;;;;;;50577:27:0;;-1:-1:-1;;;;;;;;;;;50577:27:0;50573:197;;;50625:39;;-1:-1:-1;;;;;50625:28:0;;;:39;;;;;50654:9;;50625:39;;;;50654:9;50625:28;:39;;;;;;;;;;;;;;;;;;;;;50573:197;;;50705:49;-1:-1:-1;;;;;50705:26:0;;50732:10;50744:9;50705:26;:49::i;:::-;50205:576;49883:905;;;;;;:::o;56941:692::-;57131:20;;;;:33;;;57088:77;;-1:-1:-1;;;57088:77:0;;57049:12;;;;48541:42;;57088;;:77;;57131:33;57088:77;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;57083:128;;-1:-1:-1;57190:5:0;;-1:-1:-1;57190:5:0;57182:17;;57083:128;57285:20;;;;:28;57228:86;;-1:-1:-1;;;57228:86:0;;48445:42;;57228:56;;:86;;57285:28;57228:86;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;57223:137;;-1:-1:-1;57339:5:0;;-1:-1:-1;57339:5:0;57331:17;;57223:137;57436:20;;;;:28;57466:17;;;;57406:15;;57400:84;;-1:-1:-1;;;;;57400:35:0;;;;;:84::i;:::-;57529:20;;;;:28;;57576:32;;;;;57504:121;;-1:-1:-1;;;57504:121:0;;-1:-1:-1;;;;;57504:64:0;;;;;;57576:32;57504:121;;57529:7;;57619:5;;57504:121;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;57497:128;;;;56941:692;;;;;;:::o;57899:717::-;58078:15;;;;58021:73;;-1:-1:-1;;;58021:73:0;;57983:17;;48445:42;;58021:56;;:73;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;58096:19;;;;;;;;;;;;;-1:-1:-1;;;58096:19:0;;;58013:103;;;;;-1:-1:-1;;;58013:103:0;;;;;;;;:::i;:::-;-1:-1:-1;58165:15:0;;;;58182:17;;;;58135:15;;58129:71;;-1:-1:-1;;;;;58129:35:0;;;;;:71::i;:::-;58226:15;58217:5;:24;;;;;;;;;58213:396;;;58293:7;:15;;;-1:-1:-1;;;;;58273:63:0;;58337:7;:15;;;58354:7;:16;;;58372:7;:17;;;58391:7;:19;;;58273:138;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;58258:153;;58213:396;;;58479:7;:15;;;-1:-1:-1;;;;;58459:62:0;;58522:7;:15;;;58539:7;:16;;;58557:7;:18;;;58577:7;:19;;;58459:138;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;58444:153;57899:717;-1:-1:-1;;;57899:717:0:o;48776:275::-;48839:12;-1:-1:-1;;;;;48868:31:0;;-1:-1:-1;;;;;;;;;;;48868:31:0;48864:180;;;-1:-1:-1;48926:21:0;48864:180;;;48990:42;;-1:-1:-1;;;48990:42:0;;-1:-1:-1;;;;;48990:27:0;;;;;:42;;49026:4;;48990:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;12356:122::-;12415:9;12305:6;12441:23;12445:9;12449:1;12452;12445:3;:9::i;:::-;12462:1;12305:6;12456:7;;12441:3;:23::i;:::-;:29;;;;;;;12356:122;-1:-1:-1;;;12356:122:0:o;44553:166::-;44614:7;-1:-1:-1;;;;;44638:18:0;;-1:-1:-1;;;;;;;;;;;44638:18:0;44634:33;;;-1:-1:-1;44665:2:0;44658:9;;44634:33;44693:6;-1:-1:-1;;;;;44687:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12616:120;12675:9;12727:1;12701:23;12705:11;12709:1;12305:6;12705:3;:11::i;:::-;12722:1;12718;:5;;2796:979;2926:12;2959:18;2970:6;2959:10;:18::i;:::-;2951:60;;;;-1:-1:-1;;;2951:60:0;;;;;;;:::i;:::-;3085:12;3099:23;3126:6;-1:-1:-1;;;;;3126:11:0;3146:8;3157:4;3126:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3084:78;;;;3177:7;3173:595;;;3208:10;-1:-1:-1;3201:17:0;;-1:-1:-1;3201:17:0;3173:595;3322:17;;:21;3318:439;;3585:10;3579:17;3646:15;3633:10;3629:2;3625:19;3618:44;3533:148;3728:12;3721:20;;-1:-1:-1;;;3721:20:0;;;;;;;;:::i;11575:127::-;11633:9;11663:6;;;:30;;-1:-1:-1;;11678:5:0;;;11692:1;11687;11678:5;11687:1;11673:15;;;;;:20;11663:30;11655:39;;;;;11333:113;11426:5;;;11421:16;;;;11413:25;;;;;821:619;881:4;1349:20;;1192:66;1389:23;;;;;;:42;;-1:-1:-1;;1416:15:0;;;1381:51;-1:-1:-1;;821:619:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5:130::-;72:20;;97:33;72:20;97:33;:::i;142:134::-;220:13;;238:33;220:13;238:33;:::i;454:352::-;;;584:3;577:4;569:6;565:17;561:27;551:2;;-1:-1;;592:12;551:2;-1:-1;622:20;;662:18;651:30;;648:2;;;-1:-1;;684:12;648:2;728:4;720:6;716:17;704:29;;779:3;728:4;;763:6;759:17;720:6;745:32;;742:41;739:2;;;796:1;;786:12;1958:440;;2059:3;2052:4;2044:6;2040:17;2036:27;2026:2;;-1:-1;;2067:12;2026:2;2114:6;2101:20;2136:64;2151:48;2192:6;2151:48;:::i;:::-;2136:64;:::i;:::-;2127:73;;2220:6;2213:5;2206:21;2324:3;2256:4;2315:6;2248;2306:16;;2303:25;2300:2;;;2341:1;;2331:12;2300:2;35362:6;2256:4;2248:6;2244:17;2256:4;2282:5;2278:16;35339:30;35418:1;35400:16;;;2256:4;35400:16;35393:27;2282:5;2019:379;-1:-1;;2019:379::o;2407:442::-;;2519:3;2512:4;2504:6;2500:17;2496:27;2486:2;;-1:-1;;2527:12;2486:2;2567:6;2561:13;2589:64;2604:48;2645:6;2604:48;:::i;2589:64::-;2580:73;;2673:6;2666:5;2659:21;2777:3;2709:4;2768:6;2701;2759:16;;2756:25;2753:2;;;2794:1;;2784:12;2753:2;2804:39;2836:6;2709:4;2735:5;2731:16;2709:4;2701:6;2697:17;2804:39;:::i;:::-;;2479:370;;;;:::o;6900:1179::-;;7019:4;7007:9;7002:3;6998:19;6994:30;6991:2;;;-1:-1;;7027:12;6991:2;7055:20;7019:4;7055:20;:::i;:::-;7046:29;;85:6;72:20;97:33;124:5;97:33;:::i;:::-;7135:75;;7279:2;7333:22;;72:20;97:33;72:20;97:33;:::i;:::-;7279:2;7294:16;;7287:75;7434:2;7488:22;;72:20;97:33;72:20;97:33;:::i;:::-;7467:49;7434:2;7453:5;7449:16;7442:75;;7579:2;7637:9;7633:22;9451:20;7579:2;7598:5;7594:16;7587:75;7730:3;7789:9;7785:22;9451:20;7730:3;7750:5;7746:16;7739:75;7907:3;7896:9;7892:19;7879:33;7932:18;7924:6;7921:30;7918:2;;;-1:-1;;7954:12;7918:2;7999:58;8053:3;8044:6;8033:9;8029:22;7999:58;:::i;:::-;7907:3;7985:5;7981:16;7974:84;;6985:1094;;;;:::o;8128:1249::-;;8258:4;8246:9;8241:3;8237:19;8233:30;8230:2;;;-1:-1;;8266:12;8230:2;8294:20;8258:4;8294:20;:::i;:::-;8285:29;;226:6;220:13;238:33;265:5;238:33;:::i;:::-;8374:86;;8529:2;8594:22;;220:13;238:33;220:13;238:33;:::i;:::-;8529:2;8544:16;;8537:86;8695:2;8760:22;;220:13;238:33;220:13;238:33;:::i;:::-;8728:60;8695:2;8714:5;8710:16;8703:86;;8851:2;8920:9;8916:22;9599:13;8851:2;8870:5;8866:16;8859:86;9013:3;9083:9;9079:22;9599:13;9013:3;9033:5;9029:16;9022:86;9194:3;9183:9;9179:19;9173:26;9219:18;9211:6;9208:30;9205:2;;;-1:-1;;9241:12;9205:2;9286:69;9351:3;9342:6;9331:9;9327:22;9286:69;:::i;9662:241::-;;9766:2;9754:9;9745:7;9741:23;9737:32;9734:2;;;-1:-1;;9772:12;9734:2;85:6;72:20;97:33;124:5;97:33;:::i;9910:263::-;;10025:2;10013:9;10004:7;10000:23;9996:32;9993:2;;;-1:-1;;10031:12;9993:2;226:6;220:13;238:33;265:5;238:33;:::i;10180:366::-;;;10301:2;10289:9;10280:7;10276:23;10272:32;10269:2;;;-1:-1;;10307:12;10269:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;10359:63;10459:2;10498:22;;;;9451:20;;-1:-1;;;10263:283::o;10553:1335::-;;;;;;;;;;10849:3;10837:9;10828:7;10824:23;10820:33;10817:2;;;-1:-1;;10856:12;10817:2;10914:17;10901:31;10952:18;;10944:6;10941:30;10938:2;;;-1:-1;;10974:12;10938:2;11012:80;11084:7;11075:6;11064:9;11060:22;11012:80;:::i;:::-;10994:98;;-1:-1;10994:98;-1:-1;11157:2;11142:18;;11129:32;;-1:-1;11170:30;;;11167:2;;;-1:-1;;11203:12;11167:2;11241:80;11313:7;11304:6;11293:9;11289:22;11241:80;:::i;:::-;11223:98;;-1:-1;11223:98;-1:-1;11386:2;11371:18;;11358:32;;-1:-1;11399:30;;;11396:2;;;-1:-1;;11432:12;11396:2;11470:80;11542:7;11533:6;11522:9;11518:22;11470:80;:::i;:::-;11452:98;;-1:-1;11452:98;-1:-1;11587:2;11626:22;;72:20;;-1:-1;97:33;72:20;97:33;:::i;:::-;11595:63;;-1:-1;11723:3;11708:19;;11695:33;;11737:30;;;11734:2;;;-1:-1;;11770:12;11734:2;11855:6;11844:9;11840:22;;;1727:3;1720:4;1712:6;1708:17;1704:27;1694:2;;-1:-1;;1735:12;1694:2;1778:6;1765:20;10952:18;1797:6;1794:30;1791:2;;;-1:-1;;1827:12;1791:2;1922:3;11157:2;1902:17;1863:6;1888:32;;1885:41;1882:2;;;-1:-1;;1929:12;1882:2;11157;1863:6;1859:17;11790:82;;;;;;;;10811:1077;;;;;;;;;;;:::o;11895:257::-;;12007:2;11995:9;11986:7;11982:23;11978:32;11975:2;;;-1:-1;;12013:12;11975:2;1404:6;1398:13;1416:30;1440:5;1416:30;:::i;12159:393::-;;;12288:2;12276:9;12267:7;12263:23;12259:32;12256:2;;;-1:-1;;12294:12;12256:2;1404:6;1398:13;1416:30;1440:5;1416:30;:::i;:::-;12454:2;12504:22;;;;9599:13;12346:71;;9599:13;;-1:-1;;;12250:302::o;12559:263::-;;12674:2;12662:9;12653:7;12649:23;12645:32;12642:2;;;-1:-1;;12680:12;12642:2;-1:-1;1536:13;;12636:186;-1:-1;12636:186::o;12829:345::-;;12942:2;12930:9;12921:7;12917:23;12913:32;12910:2;;;-1:-1;;12948:12;12910:2;13006:17;12993:31;13044:18;13036:6;13033:30;13030:2;;;-1:-1;;13066:12;13030:2;13096:62;13150:7;13141:6;13130:9;13126:22;13096:62;:::i;13181:999::-;;;;;;;13392:3;13380:9;13371:7;13367:23;13363:33;13360:2;;;-1:-1;;13399:12;13360:2;13457:17;13444:31;13495:18;13487:6;13484:30;13481:2;;;-1:-1;;13517:12;13481:2;13547:62;13601:7;13592:6;13581:9;13577:22;13547:62;:::i;:::-;13537:72;;;13646:2;13697:9;13693:22;358:20;383:41;418:5;383:41;:::i;:::-;13654:71;-1:-1;13762:2;13801:22;;9451:20;;-1:-1;13870:2;13909:22;;9451:20;;-1:-1;13978:3;14015:22;;1256:20;1281:30;1256:20;1281:30;:::i;:::-;13987:60;-1:-1;14084:3;14132:22;;358:20;383:41;358:20;383:41;:::i;:::-;14093:71;;;;13354:826;;;;;;;;:::o;14187:387::-;;14321:2;14309:9;14300:7;14296:23;14292:32;14289:2;;;-1:-1;;14327:12;14289:2;14385:17;14372:31;14423:18;;14415:6;14412:30;14409:2;;;-1:-1;;14445:12;14409:2;14541:6;14530:9;14526:22;;;3018:6;;3006:9;3001:3;2997:19;2993:32;2990:2;;;-1:-1;;3028:12;2990:2;3056:22;3018:6;3056:22;:::i;:::-;3047:31;;3163:49;3208:3;3184:22;3163:49;:::i;:::-;3145:16;3138:75;3311:49;3356:3;14321:2;3336:9;3332:22;3311:49;:::i;:::-;14321:2;3297:5;3293:16;3286:75;3427:2;3485:9;3481:22;9451:20;3427:2;3446:5;3442:16;3435:75;3577:2;3635:9;3631:22;9451:20;3577:2;3596:5;3592:16;3585:75;3725:3;3784:9;3780:22;9451:20;3725:3;3745:5;3741:16;3734:75;3879:3;3938:9;3934:22;9451:20;3879:3;3899:5;3895:16;3888:75;4058:49;4103:3;4024;4083:9;4079:22;4058:49;:::i;:::-;4024:3;4044:5;4040:16;4033:75;4206:49;4251:3;4172;4231:9;4227:22;4206:49;:::i;:::-;4172:3;4192:5;4188:16;4181:75;4352:3;;4341:9;4337:19;4324:33;14423:18;4369:6;4366:30;4363:2;;;-1:-1;;4399:12;4363:2;4446:58;4500:3;4491:6;4480:9;4476:22;4446:58;:::i;:::-;4352:3;4430:5;4426:18;4419:86;;;4602:3;;4591:9;4587:19;4574:33;14423:18;4619:6;4616:30;4613:2;;;-1:-1;;4649:12;4613:2;4696:79;4771:3;4762:6;4751:9;4747:22;4696:79;:::i;:::-;4676:18;;;4669:107;;;;-1:-1;4680:5;14283:291;-1:-1;;;;;14283:291::o;14581:402::-;;14726:2;14714:9;14705:7;14701:23;14697:32;14694:2;;;-1:-1;;14732:12;14694:2;14783:17;14777:24;14821:18;;14813:6;14810:30;14807:2;;;-1:-1;;14843:12;14807:2;14950:6;14939:9;14935:22;;;4976:6;;4964:9;4959:3;4955:19;4951:32;4948:2;;;-1:-1;;4986:12;4948:2;5014:22;4976:6;5014:22;:::i;:::-;5005:31;;5121:60;5177:3;5153:22;5121:60;:::i;:::-;5103:16;5096:86;5280:60;5336:3;14726:2;5316:9;5312:22;5280:60;:::i;:::-;14726:2;5266:5;5262:16;5255:86;5407:2;5476:9;5472:22;9599:13;5407:2;5426:5;5422:16;5415:86;5568:2;5637:9;5633:22;9599:13;5568:2;5587:5;5583:16;5576:86;5727:3;5797:9;5793:22;9599:13;5727:3;5747:5;5743:16;5736:86;5892:3;5962:9;5958:22;9599:13;5892:3;5912:5;5908:16;5901:86;6082:60;6138:3;6048;6118:9;6114:22;6082:60;:::i;:::-;6048:3;6068:5;6064:16;6057:86;6241:60;6297:3;6207;6277:9;6273:22;6241:60;:::i;:::-;6207:3;6227:5;6223:16;6216:86;6391:3;;6380:9;6376:19;6370:26;14821:18;6408:6;6405:30;6402:2;;;-1:-1;;6438:12;6402:2;6485:69;6550:3;6541:6;6530:9;6526:22;6485:69;:::i;:::-;6391:3;6469:5;6465:18;6458:97;;;6645:3;;6634:9;6630:19;6624:26;14821:18;6662:6;6659:30;6656:2;;;-1:-1;;6692:12;6656:2;6739:90;6825:3;6816:6;6805:9;6801:22;6739:90;:::i;15409:103::-;-1:-1;;;;;34097:54;15470:37;;15464:48::o;15750:323::-;;15882:5;32599:12;32874:6;32869:3;32862:19;15965:52;16010:6;32911:4;32906:3;32902:14;32911:4;15991:5;15987:16;15965:52;:::i;:::-;35795:7;35779:14;-1:-1;;35775:28;16029:39;;;;32911:4;16029:39;;15830:243;-1:-1;;15830:243::o;19106:1986::-;;19267:6;19367:63;19415:14;19344:16;19338:23;19367:63;:::i;:::-;19513:4;19506:5;19502:16;19496:23;19525:63;19513:4;19577:3;19573:14;19559:12;19525:63;:::i;:::-;;19672:4;19665:5;19661:16;19655:23;19672:4;19736:3;19732:14;22584:37;19832:4;19825:5;19821:16;19815:23;19832:4;19896:3;19892:14;22584:37;19990:4;19983:5;19979:16;19973:23;19990:4;20054:3;20050:14;22584:37;20153:4;20146:5;20142:16;20136:23;20153:4;20217:3;20213:14;22584:37;20307:4;20300:5;20296:16;20290:23;20319:63;20307:4;20371:3;20367:14;20353:12;20319:63;:::i;:::-;;20464:4;20457:5;20453:16;20447:23;20476:63;20464:4;20528:3;20524:14;20510:12;20476:63;:::i;:::-;;20625:6;;20618:5;20614:18;20608:25;19267:6;20625;20657:3;20653:16;20646:40;20701:71;19267:6;19262:3;19258:16;20753:12;20701:71;:::i;:::-;20693:79;;;;20865:6;;20858:5;20854:18;20848:25;20921:3;20915:4;20911:14;20865:6;20897:3;20893:16;20886:40;20941:113;21049:4;21035:12;20941:113;:::i;:::-;21076:11;19240:1852;-1:-1;;;;;;19240:1852::o;21180:1219::-;;662:18;;34108:42;;;;21406:16;21400:23;34097:54;15477:3;15470:37;34108:42;21579:4;21572:5;21568:16;21562:23;34097:54;21579:4;21643:3;21639:14;15470:37;34108:42;21744:4;21737:5;21733:16;21727:23;34097:54;21744:4;21808:3;21804:14;15470:37;;21899:4;21892:5;21888:16;21882:23;21899:4;21963:3;21959:14;22584:37;22060:4;22053:5;22049:16;22043:23;22060:4;22124:3;22120:14;22584:37;22218:4;22211:5;22207:16;22201:23;21331:4;22218;22248:3;22244:14;22237:38;22290:71;21331:4;21326:3;21322:14;22342:12;22290:71;:::i;22753:271::-;;16590:5;32599:12;16701:52;16746:6;16741:3;16734:4;16727:5;16723:16;16701:52;:::i;:::-;16765:16;;;;;22887:137;-1:-1;;22887:137::o;23031:222::-;-1:-1;;;;;34097:54;;;;15470:37;;23158:2;23143:18;;23129:124::o;23505:760::-;-1:-1;;;;;34097:54;;;15339:58;;34097:54;;23951:2;23936:18;;15339:58;23770:3;23988:2;23973:18;;23966:48;;;23505:760;;24028:78;;23755:19;;24092:6;24028:78;:::i;:::-;24154:9;24148:4;24144:20;24139:2;24128:9;24124:18;24117:48;24179:76;24250:4;24241:6;24179:76;:::i;:::-;24171:84;23741:524;-1:-1;;;;;;;23741:524::o;24272:444::-;-1:-1;;;;;34097:54;;;15470:37;;34097:54;;;;24619:2;24604:18;;15470:37;24702:2;24687:18;;22584:37;;;;24455:2;24440:18;;24426:290::o;24723:640::-;-1:-1;;;;;34097:54;;;15470:37;;34097:54;;25117:2;25102:18;;15470:37;25200:2;25185:18;;22584:37;;;24952:3;25237:2;25222:18;;25215:48;;;24723:640;;25277:76;;24937:19;;25339:6;25277:76;:::i;25370:556::-;-1:-1;;;;;34097:54;;;15470:37;;34097:54;;;;25746:2;25731:18;;15470:37;25829:2;25814:18;;22584:37;25912:2;25897:18;;22584:37;;;;25581:3;25566:19;;25552:374::o;25933:668::-;-1:-1;;;;;34097:54;;;15470:37;;34097:54;;;26337:2;26322:18;;15470:37;26420:2;26405:18;;22584:37;;;;26503:2;26488:18;;22584:37;34097:54;;;26586:3;26571:19;;15470:37;26172:3;26157:19;;26143:458::o;26608:417::-;-1:-1;;;;;34097:54;;15470:37;;26781:2;26899;26884:18;;26877:48;;;26608:417;;26939:76;;26766:18;;27001:6;26939:76;:::i;27032:345::-;-1:-1;;;;;34097:54;;;;15470:37;;34313:4;34302:16;27363:2;27348:18;;17206:56;27193:2;27178:18;;27164:213::o;27384:333::-;-1:-1;;;;;34097:54;;;;15470:37;;27703:2;27688:18;;22584:37;27539:2;27524:18;;27510:207::o;27724:210::-;33696:13;;33689:21;15704:34;;27845:2;27830:18;;27816:118::o;27941:306::-;;28086:2;28107:17;28100:47;28161:76;28086:2;28075:9;28071:18;28223:6;28161:76;:::i;28844:416::-;29044:2;29058:47;;;29029:18;;;32862:19;17889:34;32902:14;;;17869:55;17943:12;;;29015:245::o;29267:416::-;29467:2;29481:47;;;18194:2;29452:18;;;32862:19;18230:31;32902:14;;;18210:52;18281:12;;;29438:245::o;29690:416::-;29890:2;29904:47;;;18532:2;29875:18;;;32862:19;18568:34;32902:14;;;18548:55;-1:-1;;;18623:12;;;18616:34;18669:12;;;29861:245::o;30113:416::-;30313:2;30327:47;;;18920:2;30298:18;;;32862:19;-1:-1;;;32902:14;;;18936:44;18999:12;;;30284:245::o;30536:390::-;;30723:2;30744:17;30737:47;30798:118;30723:2;30712:9;30708:18;30902:6;30798:118;:::i;30933:527::-;;31161:2;31182:17;31175:47;31236:118;31161:2;31150:9;31146:18;31340:6;31236:118;:::i;:::-;31228:126;;35900:1;35893:5;35890:12;35880:2;;35906:9;35880:2;34867:39;31446:2;31435:9;31431:18;17054:63;31132:328;;;;;:::o;31467:218::-;34016:6;34005:18;;;;22475:36;;31592:2;31577:18;;31563:122::o;31692:222::-;22584:37;;;31819:2;31804:18;;31790:124::o;31921:256::-;31983:2;31977:9;32009:17;;;32084:18;32069:34;;32105:22;;;32066:62;32063:2;;;32141:1;;32131:12;32063:2;31983;32150:22;31961:216;;-1:-1;31961:216::o;32184:321::-;;32327:18;32319:6;32316:30;32313:2;;;-1:-1;;32349:12;32313:2;-1:-1;35795:7;32403:17;-1:-1;;32399:33;32490:4;32480:15;;32250:255::o;35435:268::-;35500:1;35507:101;35521:6;35518:1;35515:13;35507:101;;;35588:11;;;35582:18;35569:11;;;35562:39;35543:2;35536:10;35507:101;;;35623:6;35620:1;35617:13;35614:2;;;35500:1;35679:6;35674:3;35670:16;35663:27;35614:2;;35484:219;;;:::o;35929:117::-;-1:-1;;;;;34097:54;;35988:35;;35978:2;;36037:1;;36027:12;35978:2;35972:74;:::o;36193:111::-;36274:5;33696:13;33689:21;36252:5;36249:32;36239:2;;36295:1;;36285:12
Swarm Source
ipfs://d79495ce7deb52c0fc52ebee1eb936a1badeaa63ceb9a86b5ddf814bc2952317
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.