Source Code
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Adapter03
Compiler Version
v0.7.5+commit.eb77ed08
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "../IAdapter.sol";
import "../../lib/aavee/Aavee.sol";
import "../../lib/chai/ChaiExchange.sol";
import "../../lib/bprotocol/BProtocolAMM.sol";
import "../../lib/bzx/BZX.sol";
import "../../lib/smoothy/SmoothyV1.sol";
import "../../lib/uniswap/UniswapV1.sol";
import "../../lib/kyberdmm/KyberDmm.sol";
import "../../lib/jarvis/Jarvis.sol";
import "../../lib/lido/Lido.sol";
import "../../lib/makerpsm/MakerPsm.sol";
import "../../lib/augustus-rfq/AugustusRFQ.sol";
import "../../lib/synthetix/SynthetixAdapter.sol";
import "../../lib/lido/WstETH.sol";
import "../../lib/aave-v3/AaveV3.sol";
import "../../lib/hashflow/HashFlow.sol";
/**
* @dev This contract will route call to:
* 0 - ChaiExchange
* 1 - UniswapV1
* 2 - SmoothyV1
* 3 - BZX
* 4 - BProtocol
* 5 - Aave
* 6 - KyberDMM
* 7 - Jarvis
* 8 - Lido
* 9 - MakerPsm
* 10 - AugustusRFQ
* 11 - Synthetix
* 12 - wstETH
* 13 - AaveV3
* 14 - HashFlow
* The above are the indexes
*/
contract Adapter03 is
IAdapter,
ChaiExchange,
UniswapV1,
SmoothyV1,
BZX,
BProtocol,
Aavee,
KyberDmm,
Jarvis,
Lido,
MakerPsm,
AugustusRFQ,
Synthetix,
WstETH,
AaveV3,
HashFlow
{
using SafeMath for uint256;
/*solhint-disable no-empty-blocks*/
constructor(
uint16 aaveeRefCode,
address aaveeSpender,
address uniswapFactory,
address chai,
address dai,
address weth,
address stETH,
uint16 _aaveV3RefCode,
address _aaveV3Pool,
address _aaveV3WethGateway
)
public
WethProvider(weth)
Aavee(aaveeRefCode, aaveeSpender)
UniswapV1(uniswapFactory)
ChaiExchange(chai, dai)
Lido(stETH)
MakerPsm(dai)
AaveV3(_aaveV3RefCode, _aaveV3Pool, _aaveV3WethGateway)
{}
/*solhint-enable no-empty-blocks*/
function initialize(bytes calldata) external override {
revert("METHOD NOT IMPLEMENTED");
}
function swap(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
uint256,
Utils.Route[] calldata route
) external payable override {
for (uint256 i = 0; i < route.length; i++) {
if (route[i].index == 0) {
//swap on ChaiExchange
swapOnChai(fromToken, toToken, fromAmount.mul(route[i].percent).div(10000));
} else if (route[i].index == 1) {
//swap on Uniswap
swapOnUniswapV1(fromToken, toToken, fromAmount.mul(route[i].percent).div(10000));
} else if (route[i].index == 2) {
//swap on Smoothy
swapOnSmoothyV1(
fromToken,
toToken,
fromAmount.mul(route[i].percent).div(10000),
route[i].targetExchange,
route[i].payload
);
} else if (route[i].index == 3) {
//swap on BZX
swapOnBzx(fromToken, toToken, fromAmount.mul(route[i].percent).div(10000), route[i].payload);
} else if (route[i].index == 4) {
//swap on BProtocol
swapOnBProtocol(
fromToken,
toToken,
fromAmount.mul(route[i].percent).div(10000),
route[i].targetExchange,
route[i].payload
);
} else if (route[i].index == 5) {
//swap on aavee
swapOnAavee(
fromToken,
toToken,
fromAmount.mul(route[i].percent).div(10000),
route[i].targetExchange,
route[i].payload
);
} else if (route[i].index == 6) {
//swap on KyberDmm
swapOnKyberDmm(
fromToken,
toToken,
fromAmount.mul(route[i].percent).div(10000),
route[i].targetExchange,
route[i].payload
);
} else if (route[i].index == 7) {
//swap on Jarvis
swapOnJarvis(
fromToken,
toToken,
fromAmount.mul(route[i].percent).div(10000),
route[i].targetExchange,
route[i].payload
);
} else if (route[i].index == 8) {
//swap on Lido
swapOnLido(
fromToken,
toToken,
fromAmount.mul(route[i].percent).div(10000),
route[i].targetExchange,
route[i].payload
);
} else if (route[i].index == 9) {
//swap on MakerPsm
swapOnMakerPsm(
fromToken,
toToken,
fromAmount.mul(route[i].percent).div(10000),
route[i].targetExchange,
route[i].payload
);
} else if (route[i].index == 10) {
//swap on augustusRFQ
swapOnAugustusRFQ(
fromToken,
toToken,
fromAmount.mul(route[i].percent).div(10000),
route[i].targetExchange,
route[i].payload
);
} else if (route[i].index == 11) {
// swap on Synthetix
swapOnSynthetix(
fromToken,
toToken,
fromAmount.mul(route[i].percent).div(10000),
route[i].targetExchange,
route[i].payload
);
} else if (route[i].index == 12) {
// swap on wstETH
swapOnWstETH(fromToken, toToken, fromAmount.mul(route[i].percent).div(10000), route[i].targetExchange);
} else if (route[i].index == 13) {
//swap on AaveV3
swapOnAaveV3(fromToken, toToken, fromAmount.mul(route[i].percent).div(10000), route[i].payload);
} else if (route[i].index == 14) {
// swap on HashFlow
swapOnHashFlow(
fromToken,
toToken,
fromAmount.mul(route[i].percent).div(10000),
route[i].targetExchange,
route[i].payload
);
} else {
revert("Index not supported");
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 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(IERC20 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));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
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");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
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");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
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");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
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");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
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);
}
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "../lib/Utils.sol";
interface IAdapter {
/**
* @dev Certain adapters needs to be initialized.
* This method will be called from Augustus
*/
function initialize(bytes calldata data) external;
/**
* @dev The function which performs the swap on an exchange.
* @param fromToken Address of the source token
* @param toToken Address of the destination token
* @param fromAmount Amount of source tokens to be swapped
* @param networkFee NOT USED - Network fee to be used in this router
* @param route Route to be followed
*/
function swap(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
uint256 networkFee,
Utils.Route[] calldata route
) external payable;
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
import "./ITokenTransferProxy.sol";
contract AugustusStorage {
struct FeeStructure {
uint256 partnerShare;
bool noPositiveSlippage;
bool positiveSlippageToUser;
uint16 feePercent;
string partnerId;
bytes data;
}
ITokenTransferProxy internal tokenTransferProxy;
address payable internal feeWallet;
mapping(address => FeeStructure) internal registeredPartners;
mapping(bytes4 => address) internal selectorVsRouter;
mapping(bytes32 => bool) internal adapterInitialized;
mapping(bytes32 => bytes) internal adapterVsData;
mapping(bytes32 => bytes) internal routerData;
mapping(bytes32 => bool) internal routerInitialized;
bytes32 public constant WHITELISTED_ROLE = keccak256("WHITELISTED_ROLE");
bytes32 public constant ROUTER_ROLE = keccak256("ROUTER_ROLE");
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
interface ITokenTransferProxy {
function transferFrom(
address token,
address from,
address to,
uint256 amount
) external;
}pragma solidity 0.7.5;
pragma abicoder v2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../Utils.sol";
import "../../AugustusStorage.sol";
interface IAaveV3WETHGateway {
function depositETH(
address pool,
address onBehalfOf,
uint16 referralCode
) external payable;
function withdrawETH(
address pool,
uint256 amount,
address onBehalfOf
) external;
}
interface IAaveV3Pool {
function supply(
IERC20 asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
function withdraw(
IERC20 asset,
uint256 amount,
address to
) external returns (uint256);
}
contract AaveV3 {
struct AaveData {
address aToken;
}
uint16 public immutable aaveV3RefCode;
address public immutable aaveV3Pool;
address public immutable aaveV3WethGateway;
constructor(
uint16 _refCode,
address _pool,
address _wethGateway
) public {
aaveV3RefCode = _refCode;
aaveV3Pool = _pool;
aaveV3WethGateway = _wethGateway;
}
function swapOnAaveV3(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
bytes calldata payload
) internal {
_swapOnAaveV3(fromToken, toToken, fromAmount, payload);
}
function buyOnAaveV3(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
bytes calldata payload
) internal {
_swapOnAaveV3(fromToken, toToken, fromAmount, payload);
}
function _swapOnAaveV3(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
bytes memory payload
) private {
AaveData memory data = abi.decode(payload, (AaveData));
if (address(fromToken) == address(data.aToken)) {
if (address(toToken) == Utils.ethAddress()) {
Utils.approve(aaveV3WethGateway, address(fromToken), fromAmount);
IAaveV3WETHGateway(aaveV3WethGateway).withdrawETH(aaveV3Pool, fromAmount, address(this));
} else {
Utils.approve(aaveV3Pool, address(fromToken), fromAmount);
IAaveV3Pool(aaveV3Pool).withdraw(toToken, fromAmount, address(this));
}
} else if (address(toToken) == address(data.aToken)) {
if (address(fromToken) == Utils.ethAddress()) {
IAaveV3WETHGateway(aaveV3WethGateway).depositETH{ value: fromAmount }(
aaveV3Pool,
address(this),
aaveV3RefCode
);
} else {
Utils.approve(aaveV3Pool, address(fromToken), fromAmount);
IAaveV3Pool(aaveV3Pool).supply(fromToken, fromAmount, address(this), aaveV3RefCode);
}
} else {
revert("Invalid aToken");
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IAavee.sol";
import "../Utils.sol";
contract Aavee {
struct AaveeDataV1 {
address aToken;
}
uint16 public immutable refCodeV1;
address public immutable spender;
constructor(uint16 _refCode, address _spender) public {
refCodeV1 = _refCode;
spender = _spender;
}
function swapOnAavee(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes calldata payload
) internal {
_swapOnAavee(fromToken, toToken, fromAmount, exchange, payload);
}
function buyOnAavee(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes calldata payload
) internal {
_swapOnAavee(fromToken, toToken, fromAmount, exchange, payload);
}
function _swapOnAavee(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes memory payload
) private {
AaveeDataV1 memory data = abi.decode(payload, (AaveeDataV1));
Utils.approve(spender, address(fromToken), fromAmount);
if (address(fromToken) == address(data.aToken)) {
require(IAaveToken(data.aToken).underlyingAssetAddress() == address(toToken), "Invalid to token");
IAaveToken(data.aToken).redeem(fromAmount);
} else if (address(toToken) == address(data.aToken)) {
require(IAaveToken(data.aToken).underlyingAssetAddress() == address(fromToken), "Invalid to token");
if (address(fromToken) == Utils.ethAddress()) {
IAaveV1LendingPool(exchange).deposit{ value: fromAmount }(fromToken, fromAmount, refCodeV1);
} else {
IAaveV1LendingPool(exchange).deposit(fromToken, fromAmount, refCodeV1);
}
} else {
revert("Invalid aToken");
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IAaveToken {
function redeem(uint256 amount) external;
function underlyingAssetAddress() external view returns (address);
}
interface IAaveV1LendingPool {
function deposit(
IERC20 token,
uint256 amount,
uint16 refCode
) external payable;
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IAugustusRFQ.sol";
import "../Utils.sol";
import "../WethProvider.sol";
import "../weth/IWETH.sol";
abstract contract AugustusRFQ is WethProvider {
using SafeMath for uint256;
struct AugustusRFQData {
IAugustusRFQ.OrderInfo[] orderInfos;
}
function swapOnAugustusRFQ(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes calldata payload
) internal {
AugustusRFQData memory data = abi.decode(payload, (AugustusRFQData));
for (uint256 i = 0; i < data.orderInfos.length; ++i) {
address userAddress = address(uint160(data.orderInfos[i].order.nonceAndMeta));
require(userAddress == address(0) || userAddress == msg.sender, "unauthorized user");
}
if (address(fromToken) == Utils.ethAddress()) {
IWETH(WETH).deposit{ value: fromAmount }();
Utils.approve(exchange, WETH, fromAmount);
} else {
Utils.approve(exchange, address(fromToken), fromAmount);
}
IAugustusRFQ(exchange).tryBatchFillOrderTakerAmount(data.orderInfos, fromAmount, address(this));
if (address(toToken) == Utils.ethAddress()) {
uint256 amount = IERC20(WETH).balanceOf(address(this));
IWETH(WETH).withdraw(amount);
}
}
function buyOnAugustusRFQ(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmountMax,
uint256 toAmount,
address exchange,
bytes calldata payload
) internal {
AugustusRFQData memory data = abi.decode(payload, (AugustusRFQData));
for (uint256 i = 0; i < data.orderInfos.length; ++i) {
address userAddress = address(uint160(data.orderInfos[i].order.nonceAndMeta));
require(userAddress == address(0) || userAddress == msg.sender, "unauthorized user");
}
if (address(fromToken) == Utils.ethAddress()) {
IWETH(WETH).deposit{ value: fromAmountMax }();
Utils.approve(exchange, WETH, fromAmountMax);
} else {
Utils.approve(exchange, address(fromToken), fromAmountMax);
}
IAugustusRFQ(exchange).tryBatchFillOrderMakerAmount(data.orderInfos, toAmount, address(this));
if (address(fromToken) == Utils.ethAddress() || address(toToken) == Utils.ethAddress()) {
uint256 amount = IERC20(WETH).balanceOf(address(this));
IWETH(WETH).withdraw(amount);
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
interface IAugustusRFQ {
struct Order {
uint256 nonceAndMeta; // first 160 bits is user address and then nonce
uint128 expiry;
address makerAsset;
address takerAsset;
address maker;
address taker; // zero address on orders executable by anyone
uint256 makerAmount;
uint256 takerAmount;
}
// makerAsset and takerAsset are Packed structures
// 0 - 159 bits are address
// 160 - 161 bits are tokenType (0 ERC20, 1 ERC1155, 2 ERC721)
struct OrderNFT {
uint256 nonceAndMeta; // first 160 bits is user address and then nonce
uint128 expiry;
uint256 makerAsset;
uint256 makerAssetId; // simply ignored in case of ERC20s
uint256 takerAsset;
uint256 takerAssetId; // simply ignored in case of ERC20s
address maker;
address taker; // zero address on orders executable by anyone
uint256 makerAmount;
uint256 takerAmount;
}
struct OrderInfo {
Order order;
bytes signature;
uint256 takerTokenFillAmount;
bytes permitTakerAsset;
bytes permitMakerAsset;
}
struct OrderNFTInfo {
OrderNFT order;
bytes signature;
uint256 takerTokenFillAmount;
bytes permitTakerAsset;
bytes permitMakerAsset;
}
/**
@dev Allows taker to fill complete RFQ order
@param order Order quote to fill
@param signature Signature of the maker corresponding to the order
*/
function fillOrder(Order calldata order, bytes calldata signature) external;
/**
@dev Allows taker to fill Limit order
@param order Order quote to fill
@param signature Signature of the maker corresponding to the order
*/
function fillOrderNFT(OrderNFT calldata order, bytes calldata signature) external;
/**
@dev Same as fillOrder but allows sender to specify the target
@param order Order quote to fill
@param signature Signature of the maker corresponding to the order
@param target Address of the receiver
*/
function fillOrderWithTarget(
Order calldata order,
bytes calldata signature,
address target
) external;
/**
@dev Same as fillOrderNFT but allows sender to specify the target
@param order Order quote to fill
@param signature Signature of the maker corresponding to the order
@param target Address of the receiver
*/
function fillOrderWithTargetNFT(
OrderNFT calldata order,
bytes calldata signature,
address target
) external;
/**
@dev Allows taker to partially fill an order
@param order Order quote to fill
@param signature Signature of the maker corresponding to the order
@param takerTokenFillAmount Maximum taker token to fill this order with.
*/
function partialFillOrder(
Order calldata order,
bytes calldata signature,
uint256 takerTokenFillAmount
) external returns (uint256 makerTokenFilledAmount);
/**
@dev Allows taker to partially fill an NFT order
@param order Order quote to fill
@param signature Signature of the maker corresponding to the order
@param takerTokenFillAmount Maximum taker token to fill this order with.
*/
function partialFillOrderNFT(
OrderNFT calldata order,
bytes calldata signature,
uint256 takerTokenFillAmount
) external returns (uint256 makerTokenFilledAmount);
/**
@dev Same as `partialFillOrder` but it allows to specify the destination address
@param order Order quote to fill
@param signature Signature of the maker corresponding to the order
@param takerTokenFillAmount Maximum taker token to fill this order with.
@param target Address that will receive swap funds
*/
function partialFillOrderWithTarget(
Order calldata order,
bytes calldata signature,
uint256 takerTokenFillAmount,
address target
) external returns (uint256 makerTokenFilledAmount);
/**
@dev Same as `partialFillOrderWithTarget` but it allows to pass permit
@param order Order quote to fill
@param signature Signature of the maker corresponding to the order
@param takerTokenFillAmount Maximum taker token to fill this order with.
@param target Address that will receive swap funds
@param permitTakerAsset Permit calldata for taker
@param permitMakerAsset Permit calldata for maker
*/
function partialFillOrderWithTargetPermit(
Order calldata order,
bytes calldata signature,
uint256 takerTokenFillAmount,
address target,
bytes calldata permitTakerAsset,
bytes calldata permitMakerAsset
) external returns (uint256 makerTokenFilledAmount);
/**
@dev Same as `partialFillOrderNFT` but it allows to specify the destination address
@param order Order quote to fill
@param signature Signature of the maker corresponding to the order
@param takerTokenFillAmount Maximum taker token to fill this order with.
@param target Address that will receive swap funds
*/
function partialFillOrderWithTargetNFT(
OrderNFT calldata order,
bytes calldata signature,
uint256 takerTokenFillAmount,
address target
) external returns (uint256 makerTokenFilledAmount);
/**
@dev Same as `partialFillOrderWithTargetNFT` but it allows to pass token permits
@param order Order quote to fill
@param signature Signature of the maker corresponding to the order
@param takerTokenFillAmount Maximum taker token to fill this order with.
@param target Address that will receive swap funds
@param permitTakerAsset Permit calldata for taker
@param permitMakerAsset Permit calldata for maker
*/
function partialFillOrderWithTargetPermitNFT(
OrderNFT calldata order,
bytes calldata signature,
uint256 takerTokenFillAmount,
address target,
bytes calldata permitTakerAsset,
bytes calldata permitMakerAsset
) external returns (uint256 makerTokenFilledAmount);
/**
@dev Partial fill multiple orders
@param orderInfos OrderInfo to fill
@param target Address of receiver
*/
function batchFillOrderWithTarget(OrderInfo[] calldata orderInfos, address target) external;
/**
@dev batch fills orders until the takerFillAmount is swapped
@dev skip the order if it fails
@param orderInfos OrderInfo to fill
@param takerFillAmount total taker amount to fill
@param target Address of receiver
*/
function tryBatchFillOrderTakerAmount(
OrderInfo[] calldata orderInfos,
uint256 takerFillAmount,
address target
) external;
/**
@dev batch fills orders until the makerFillAmount is swapped
@dev skip the order if it fails
@param orderInfos OrderInfo to fill
@param makerFillAmount total maker amount to fill
@param target Address of receiver
*/
function tryBatchFillOrderMakerAmount(
OrderInfo[] calldata orderInfos,
uint256 makerFillAmount,
address target
) external;
/**
@dev Partial fill multiple NFT orders
@param orderInfos Info about each order to fill
@param target Address of receiver
*/
function batchFillOrderWithTargetNFT(OrderNFTInfo[] calldata orderInfos, address target) external;
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "../Utils.sol";
interface IBalancerV2Vault {
enum SwapKind {
GIVEN_IN,
GIVEN_OUT
}
struct SingleSwap {
bytes32 poolId;
SwapKind kind;
address assetIn;
address assetOut;
uint256 amount;
bytes userData;
}
struct BatchSwapStep {
bytes32 poolId;
uint256 assetInIndex;
uint256 assetOutIndex;
uint256 amount;
bytes userData;
}
struct FundManagement {
address sender;
bool fromInternalBalance;
address payable recipient;
bool toInternalBalance;
}
function swap(
SingleSwap memory singleSwap,
FundManagement memory funds,
uint256 limit,
uint256 deadline
) external payable returns (uint256);
function batchSwap(
SwapKind kind,
BatchSwapStep[] memory swaps,
address[] memory assets,
FundManagement memory funds,
int256[] memory limits,
uint256 deadline
) external payable returns (int256[] memory);
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../Utils.sol";
import "./IBProtocolAMM.sol";
contract BProtocol {
function swapOnBProtocol(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes calldata payload
) internal {
Utils.approve(address(exchange), address(fromToken), fromAmount);
IBProtocolAMM(exchange).swap(fromAmount, 1, payable(address(this)));
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
interface IBProtocolAMM {
function swap(
uint256 lusdAmount,
uint256 minEthReturn,
address payable dest
) external returns (uint256);
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "./IBZX.sol";
import "../Utils.sol";
import "../WethProvider.sol";
abstract contract BZX is WethProvider {
struct BZXData {
address iToken;
}
function swapOnBzx(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
bytes calldata payload
) internal {
_swapOnBZX(fromToken, toToken, fromAmount, payload);
}
function buyOnBzx(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
bytes calldata payload
) internal {
_swapOnBZX(fromToken, toToken, fromAmount, payload);
}
function _swapOnBZX(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
bytes memory payload
) private {
BZXData memory data = abi.decode(payload, (BZXData));
Utils.approve(address(data.iToken), address(fromToken), fromAmount);
if (address(fromToken) == address(data.iToken)) {
if (address(toToken) == Utils.ethAddress()) {
require(IBZX(data.iToken).loanTokenAddress() == WETH, "Invalid to token");
IBZX(data.iToken).burnToEther(payable(address(this)), fromAmount);
} else {
require(IBZX(data.iToken).loanTokenAddress() == address(toToken), "Invalid to token");
IBZX(data.iToken).burn(address(this), fromAmount);
}
} else if (address(toToken) == address(data.iToken)) {
if (address(fromToken) == Utils.ethAddress()) {
require(IBZX(data.iToken).loanTokenAddress() == WETH, "Invalid from token");
IBZX(data.iToken).mintWithEther{ value: fromAmount }(address(this));
} else {
require(IBZX(data.iToken).loanTokenAddress() == address(fromToken), "Invalid from token");
IBZX(data.iToken).mint(address(this), fromAmount);
}
} else {
revert("Invalid token pair!!");
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
interface IBZX {
function mint(address receiver, uint256 depositAmount) external returns (uint256 mintAmount);
function mintWithEther(address receiver) external payable returns (uint256 mintAmount);
function burn(address receiver, uint256 burnAmount) external returns (uint256 loanAmountPaid);
function burnToEther(address payable receiver, uint256 burnAmount) external returns (uint256 loanAmountPaid);
function loanTokenAddress() external view returns (address);
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IChai.sol";
import "../Utils.sol";
contract ChaiExchange {
address public immutable chai;
address public immutable dai;
constructor(address _chai, address _dai) public {
chai = _chai;
dai = _dai;
}
function swapOnChai(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount
) internal {
_swapOnChai(fromToken, toToken, fromAmount);
}
function buyOnChai(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount
) internal {
_swapOnChai(fromToken, toToken, fromAmount);
}
function _swapOnChai(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount
) private {
Utils.approve(address(chai), address(fromToken), fromAmount);
if (address(fromToken) == chai) {
require(address(toToken) == dai, "Destination token should be dai");
IChai(chai).exit(address(this), fromAmount);
} else if (address(fromToken) == dai) {
require(address(toToken) == chai, "Destination token should be chai");
IChai(chai).join(address(this), fromAmount);
} else {
revert("Invalid fromToken");
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
interface IChai {
function join(address dst, uint256 wad) external;
function exit(address src, uint256 wad) external;
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "../Utils.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IQuote {
struct RFQTQuote {
address pool;
address externalAccount;
address trader;
address effectiveTrader;
address baseToken;
address quoteToken;
uint256 effectiveBaseTokenAmount;
uint256 maxBaseTokenAmount;
uint256 maxQuoteTokenAmount;
uint256 quoteExpiry;
uint256 nonce;
bytes32 txid;
bytes signature;
}
}
interface IHashFlowRouter {
function tradeSingleHop(IQuote.RFQTQuote calldata quote) external payable;
}
contract HashFlow {
struct HashFlowData {
address pool;
address quoteToken;
address externalAccount;
uint256 baseTokenAmount;
uint256 quoteTokenAmount;
uint256 quoteExpiry;
uint256 nonce;
bytes32 txid;
bytes signature;
}
function buyOnHashFlow(
IERC20 fromToken,
IERC20 toToken,
uint256 maxFromAmount,
uint256 toAmount,
address targetExchange,
bytes calldata payload
) internal {
HashFlowData memory data = abi.decode(payload, (HashFlowData));
require(data.quoteTokenAmount >= toAmount, "HashFlow quoteTokenAmount < toAmount");
if (address(fromToken) == Utils.ethAddress()) {
IHashFlowRouter(targetExchange).tradeSingleHop{ value: data.baseTokenAmount }(
IQuote.RFQTQuote({
pool: data.pool,
externalAccount: data.externalAccount,
trader: address(this),
effectiveTrader: msg.sender,
baseToken: address(0),
quoteToken: address(toToken),
effectiveBaseTokenAmount: maxFromAmount > data.baseTokenAmount
? data.baseTokenAmount
: maxFromAmount,
maxBaseTokenAmount: data.baseTokenAmount,
maxQuoteTokenAmount: data.quoteTokenAmount,
quoteExpiry: data.quoteExpiry,
nonce: data.nonce,
txid: data.txid,
signature: data.signature
})
);
} else {
Utils.approve(targetExchange, address(fromToken), data.baseTokenAmount);
IHashFlowRouter(targetExchange).tradeSingleHop(
IQuote.RFQTQuote({
pool: data.pool,
externalAccount: data.externalAccount,
trader: address(this),
effectiveTrader: msg.sender,
baseToken: address(fromToken),
quoteToken: data.quoteToken,
effectiveBaseTokenAmount: maxFromAmount > data.baseTokenAmount
? data.baseTokenAmount
: maxFromAmount,
maxBaseTokenAmount: data.baseTokenAmount,
maxQuoteTokenAmount: data.quoteTokenAmount,
quoteExpiry: data.quoteExpiry,
nonce: data.nonce,
txid: data.txid,
signature: data.signature
})
);
}
}
function swapOnHashFlow(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes calldata payload
) internal {
HashFlowData memory data = abi.decode(payload, (HashFlowData));
if (address(fromToken) == Utils.ethAddress()) {
IHashFlowRouter(exchange).tradeSingleHop{ value: data.baseTokenAmount }(
IQuote.RFQTQuote({
pool: data.pool,
externalAccount: data.externalAccount,
trader: address(this),
effectiveTrader: msg.sender,
baseToken: address(0),
quoteToken: address(toToken),
effectiveBaseTokenAmount: fromAmount > data.baseTokenAmount ? data.baseTokenAmount : fromAmount,
maxBaseTokenAmount: data.baseTokenAmount,
maxQuoteTokenAmount: data.quoteTokenAmount,
quoteExpiry: data.quoteExpiry,
nonce: data.nonce,
txid: data.txid,
signature: data.signature
})
);
} else {
Utils.approve(exchange, address(fromToken), data.baseTokenAmount);
IHashFlowRouter(exchange).tradeSingleHop(
IQuote.RFQTQuote({
pool: data.pool,
externalAccount: data.externalAccount,
trader: address(this),
effectiveTrader: msg.sender,
baseToken: address(fromToken),
quoteToken: data.quoteToken,
effectiveBaseTokenAmount: fromAmount > data.baseTokenAmount ? data.baseTokenAmount : fromAmount,
maxBaseTokenAmount: data.baseTokenAmount,
maxQuoteTokenAmount: data.quoteTokenAmount,
quoteExpiry: data.quoteExpiry,
nonce: data.nonce,
txid: data.txid,
signature: data.signature
})
);
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../Utils.sol";
interface IJarvisPool {
struct MintParams {
// Derivative to use
address derivative;
// Minimum amount of synthetic tokens that a user wants to mint using collateral (anti-slippage)
uint256 minNumTokens;
// Amount of collateral that a user wants to spend for minting
uint256 collateralAmount;
// Maximum amount of fees in percentage that user is willing to pay
uint256 feePercentage;
// Expiration time of the transaction
uint256 expiration;
// Address to which send synthetic tokens minted
address recipient;
}
struct RedeemParams {
// Derivative to use
address derivative;
// Amount of synthetic tokens that user wants to use for redeeming
uint256 numTokens;
// Minimium amount of collateral that user wants to redeem (anti-slippage)
uint256 minCollateral;
// Maximum amount of fees in percentage that user is willing to pay
uint256 feePercentage;
// Expiration time of the transaction
uint256 expiration;
// Address to which send collateral tokens redeemed
address recipient;
}
struct ExchangeParams {
// Derivative of source pool
address derivative;
// Destination pool
address destPool;
// Derivative of destination pool
address destDerivative;
// Amount of source synthetic tokens that user wants to use for exchanging
uint256 numTokens;
// Minimum Amount of destination synthetic tokens that user wants to receive (anti-slippage)
uint256 minDestNumTokens;
// Maximum amount of fees in percentage that user is willing to pay
uint256 feePercentage;
// Expiration time of the transaction
uint256 expiration;
// Address to which send synthetic tokens exchanged
address recipient;
}
function mint(MintParams memory mintParams) external returns (uint256 syntheticTokensMinted, uint256 feePaid);
function redeem(RedeemParams memory redeemParams) external returns (uint256 collateralRedeemed, uint256 feePaid);
function exchange(ExchangeParams memory exchangeParams)
external
returns (uint256 destNumTokensMinted, uint256 feePaid);
}
contract Jarvis {
enum MethodType {
mint,
redeem,
exchange
}
struct JarvisData {
uint256 opType;
address derivatives;
address destDerivatives;
uint128 fee;
address destPool;
uint128 expiration;
}
function swapOnJarvis(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes calldata payload
) internal {
JarvisData memory data = abi.decode(payload, (JarvisData));
Utils.approve(exchange, address(fromToken), fromAmount);
if (data.opType == uint256(MethodType.mint)) {
IJarvisPool.MintParams memory mintParam = IJarvisPool.MintParams(
data.derivatives,
1,
fromAmount,
data.fee,
data.expiration,
address(this)
);
IJarvisPool(exchange).mint(mintParam);
} else if (data.opType == uint256(MethodType.redeem)) {
IJarvisPool.RedeemParams memory redeemParam = IJarvisPool.RedeemParams(
data.derivatives,
fromAmount,
1,
data.fee,
data.expiration,
address(this)
);
IJarvisPool(exchange).redeem(redeemParam);
} else if (data.opType == uint256(MethodType.exchange)) {
IJarvisPool.ExchangeParams memory exchangeParam = IJarvisPool.ExchangeParams(
data.derivatives,
data.destPool,
data.destDerivatives,
fromAmount,
1,
data.fee,
data.expiration,
address(this)
);
IJarvisPool(exchange).exchange(exchangeParam);
} else {
revert("Invalid opType");
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IDMMExchangeRouter {
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata poolsPath,
IERC20[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata poolsPath,
IERC20[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../Utils.sol";
import "../weth/IWETH.sol";
import "../WethProvider.sol";
import "./IKyberDmmRouter.sol";
abstract contract KyberDmm is WethProvider {
uint256 constant MAX_INT = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
struct KyberDMMData {
address[] poolPath;
IERC20[] path;
}
function swapOnKyberDmm(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes calldata payload
) internal {
KyberDMMData memory data = abi.decode(payload, (KyberDMMData));
address _fromToken = address(fromToken) == Utils.ethAddress() ? WETH : address(fromToken);
address _toToken = address(toToken) == Utils.ethAddress() ? WETH : address(toToken);
if (address(fromToken) == Utils.ethAddress()) {
IWETH(WETH).deposit{ value: fromAmount }();
}
Utils.approve(address(exchange), _fromToken, fromAmount);
IDMMExchangeRouter(exchange).swapExactTokensForTokens(
fromAmount,
1,
data.poolPath,
data.path,
address(this),
MAX_INT // deadline
);
if (address(toToken) == Utils.ethAddress()) {
IWETH(WETH).withdraw(IERC20(WETH).balanceOf(address(this)));
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
interface IstETH {
function submit(address _referral) external payable returns (uint256);
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
interface IwstETH {
function wrap(uint256 _stETHAmount) external returns (uint256);
function unwrap(uint256 _wstETHAmount) external returns (uint256);
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../Utils.sol";
import "./IstETH.sol";
contract Lido {
address public immutable stETH;
constructor(address _stETH) public {
stETH = _stETH;
}
function swapOnLido(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes calldata payload
) internal {
require(address(fromToken) == Utils.ethAddress(), "srcToken should be ETH");
require(address(toToken) == stETH, "destToken should be stETH");
IstETH(stETH).submit{ value: fromAmount }(address(0));
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../Utils.sol";
import "./IwstETH.sol";
contract WstETH {
function swapOnWstETH(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange
) internal {
bool wrapping = address(toToken) == exchange;
bool unwrapping = address(fromToken) == exchange;
require((wrapping && !unwrapping) || (unwrapping && !wrapping), "One token should be wstETH");
if (wrapping) {
Utils.approve(exchange, address(fromToken), fromAmount);
IwstETH(exchange).wrap(fromAmount);
} else {
IwstETH(exchange).unwrap(fromAmount);
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
interface IPsm {
function sellGem(address usr, uint256 gemAmt) external;
function buyGem(address usr, uint256 gemAmt) external;
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IPsm.sol";
import "../Utils.sol";
contract MakerPsm {
using SafeMath for uint256;
address immutable daiMaker; // dai name has collision with chai
uint256 constant WAD = 1e18;
struct MakerPsmData {
address gemJoinAddress;
uint256 toll;
uint256 to18ConversionFactor;
}
constructor(address _dai) public {
daiMaker = _dai;
}
function swapOnMakerPsm(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes calldata payload
) internal {
MakerPsmData memory makerPsmData = abi.decode(payload, (MakerPsmData));
if (address(fromToken) == daiMaker) {
uint256 gemAmt = fromAmount.mul(WAD).div(WAD.add(makerPsmData.toll).mul(makerPsmData.to18ConversionFactor));
Utils.approve(exchange, address(fromToken), fromAmount);
IPsm(exchange).buyGem(address(this), gemAmt);
} else {
Utils.approve(makerPsmData.gemJoinAddress, address(fromToken), fromAmount);
IPsm(exchange).sellGem(address(this), fromAmount);
}
}
function buyOnMakerPsm(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
uint256 toAmount,
address exchange,
bytes calldata payload
) internal {
MakerPsmData memory makerPsmData = abi.decode(payload, (MakerPsmData));
if (address(fromToken) == daiMaker) {
Utils.approve(exchange, address(fromToken), fromAmount);
IPsm(exchange).buyGem(address(this), toAmount);
} else {
uint256 a = toAmount.mul(WAD);
uint256 b = WAD.sub(makerPsmData.toll).mul(makerPsmData.to18ConversionFactor);
// ceil division to handle rounding error
uint256 gemAmt = (a.add(b).sub(1)).div(b);
Utils.approve(makerPsmData.gemJoinAddress, address(fromToken), fromAmount);
IPsm(exchange).sellGem(address(this), gemAmt);
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
interface ISmoothyV1 {
function swap(
uint256 bTokenIdxIn,
uint256 bTokenIdxOut,
uint256 bTokenInAmount,
uint256 bTokenOutMin
) external;
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../Utils.sol";
import "./ISmoothyV1.sol";
import "../weth/IWETH.sol";
contract SmoothyV1 {
struct SmoothyV1Data {
uint256 i;
uint256 j;
}
function swapOnSmoothyV1(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes calldata payload
) internal {
SmoothyV1Data memory data = abi.decode(payload, (SmoothyV1Data));
Utils.approve(exchange, address(fromToken), fromAmount);
ISmoothyV1(exchange).swap(data.i, data.j, fromAmount, 1);
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma abicoder v2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../Utils.sol";
interface ISynthetix {
function exchangeAtomically(
bytes32 sourceCurrencyKey,
uint256 sourceAmount,
bytes32 destinationCurrencyKey,
bytes32 trackingCode,
uint256 minAmount
) external returns (uint256 amountReceived);
function exchange(
bytes32 sourceCurrencyKey,
uint256 sourceAmount,
bytes32 destinationCurrencyKey
) external returns (uint256 amountReceived);
}
abstract contract Synthetix {
// Atomic exchanges work only with sTokens, so no need to wrap/unwrap them
struct SynthetixData {
bytes32 trackingCode;
bytes32 srcCurrencyKey;
bytes32 destCurrencyKey;
// 0 - exchangeAtomically
// 1 - exchange
int8 exchangeType;
}
function swapOnSynthetix(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
address exchange,
bytes calldata payload
) internal {
SynthetixData memory synthetixData = abi.decode(payload, (SynthetixData));
Utils.approve(exchange, address(fromToken), fromAmount);
if (synthetixData.exchangeType == 0) {
ISynthetix(exchange).exchangeAtomically(
synthetixData.srcCurrencyKey,
fromAmount,
synthetixData.destCurrencyKey,
synthetixData.trackingCode,
1
);
} else {
ISynthetix(exchange).exchange(synthetixData.srcCurrencyKey, fromAmount, synthetixData.destCurrencyKey);
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
interface IUniswapExchange {
function ethToTokenSwapInput(uint256 minTokens, uint256 deadline) external payable returns (uint256 tokensBought);
function ethToTokenSwapOutput(uint256 tokensBought, uint256 deadline) external payable returns (uint256 ethSold);
function tokenToEthSwapInput(
uint256 tokensSold,
uint256 minEth,
uint256 deadline
) external returns (uint256 ethBought);
function tokenToEthSwapOutput(
uint256 ethBought,
uint256 maxTokens,
uint256 deadline
) external returns (uint256 tokensSold);
function tokenToTokenSwapInput(
uint256 tokensSold,
uint256 minTokensBought,
uint256 minEthBought,
uint256 deadline,
address tokenAddr
) external returns (uint256 tokensBought);
function tokenToTokenSwapOutput(
uint256 tokensBought,
uint256 maxTokensSold,
uint256 maxEthSold,
uint256 deadline,
address toToken
) external returns (uint256 tokensSold);
function ethToTokenTransferInput(
uint256 min_tokens,
uint256 deadline,
address recipient
) external payable returns (uint256 tokens_bought);
function ethToTokenTransferOutput(
uint256 tokens_bought,
uint256 deadline,
address recipient
) external payable returns (uint256 eth_sold);
function tokenToEthTransferInput(
uint256 tokens_sold,
uint256 min_tokens,
uint256 deadline,
address recipient
) external returns (uint256 eth_bought);
function tokenToEthTransferOutput(
uint256 eth_bought,
uint256 max_tokens,
uint256 deadline,
address recipient
) external returns (uint256 tokens_sold);
function tokenToTokenTransferInput(
uint256 tokens_sold,
uint256 min_tokens_bought,
uint256 min_eth_bought,
uint256 deadline,
address recipient,
address token_addr
) external returns (uint256 tokens_bought);
function tokenToTokenTransferOutput(
uint256 tokens_bought,
uint256 max_tokens_sold,
uint256 max_eth_sold,
uint256 deadline,
address recipient,
address token_addr
) external returns (uint256 tokens_sold);
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
import "./IUniswapExchange.sol";
interface IUniswapFactory {
function getExchange(address token) external view returns (address exchange);
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../Utils.sol";
import "./IUniswapExchange.sol";
import "./IUniswapFactory.sol";
contract UniswapV1 {
using SafeMath for uint256;
address public immutable factory;
constructor(address _factory) public {
factory = _factory;
}
function swapOnUniswapV1(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount
) internal {
_swapOnUniswapV1(fromToken, toToken, fromAmount, 1);
}
function buyOnUniswapV1(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
uint256 toAmount
) internal {
address exchange = getExchange(fromToken, toToken);
Utils.approve(address(exchange), address(fromToken), fromAmount);
if (address(fromToken) == Utils.ethAddress()) {
IUniswapExchange(exchange).ethToTokenSwapOutput{ value: fromAmount }(toAmount, block.timestamp);
} else if (address(toToken) == Utils.ethAddress()) {
IUniswapExchange(exchange).tokenToEthSwapOutput(toAmount, fromAmount, block.timestamp);
} else {
IUniswapExchange(exchange).tokenToTokenSwapOutput(
toAmount,
fromAmount,
Utils.maxUint(),
block.timestamp,
address(toToken)
);
}
}
function getExchange(IERC20 fromToken, IERC20 toToken) private view returns (address) {
address exchangeAddress = address(fromToken) == Utils.ethAddress() ? address(toToken) : address(fromToken);
return IUniswapFactory(factory).getExchange(exchangeAddress);
}
function _swapOnUniswapV1(
IERC20 fromToken,
IERC20 toToken,
uint256 fromAmount,
uint256 toAmount
) private returns (uint256) {
address exchange = getExchange(fromToken, toToken);
Utils.approve(exchange, address(fromToken), fromAmount);
uint256 receivedAmount = 0;
if (address(fromToken) == Utils.ethAddress()) {
receivedAmount = IUniswapExchange(exchange).ethToTokenSwapInput{ value: fromAmount }(
toAmount,
block.timestamp
);
} else if (address(toToken) == Utils.ethAddress()) {
receivedAmount = IUniswapExchange(exchange).tokenToEthSwapInput(fromAmount, toAmount, block.timestamp);
} else {
receivedAmount = IUniswapExchange(exchange).tokenToTokenSwapInput(
fromAmount,
toAmount,
1,
block.timestamp,
address(toToken)
);
}
return receivedAmount;
}
}/*solhint-disable avoid-low-level-calls */
// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "../ITokenTransferProxy.sol";
import { IBalancerV2Vault } from "./balancerv2/IBalancerV2Vault.sol";
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
interface IERC20PermitLegacy {
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
library Utils {
using SafeMath for uint256;
using SafeERC20 for IERC20;
address private constant ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
uint256 private constant MAX_UINT = type(uint256).max;
enum CurveSwapType {
EXCHANGE,
EXCHANGE_UNDERLYING,
EXCHANGE_GENERIC_FACTORY_ZAP
}
/**
* @param fromToken Address of the source token
* @param fromAmount Amount of source tokens to be swapped
* @param toAmount Minimum destination token amount expected out of this swap
* @param expectedAmount Expected amount of destination tokens without slippage
* @param beneficiary Beneficiary address
* 0 then 100% will be transferred to beneficiary. Pass 10000 for 100%
* @param path Route to be taken for this swap to take place
*/
struct SellData {
address fromToken;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
address payable beneficiary;
Utils.Path[] path;
address payable partner;
uint256 feePercent;
bytes permit;
uint256 deadline;
bytes16 uuid;
}
struct BuyData {
address adapter;
address fromToken;
address toToken;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
address payable beneficiary;
Utils.Route[] route;
address payable partner;
uint256 feePercent;
bytes permit;
uint256 deadline;
bytes16 uuid;
}
struct MegaSwapSellData {
address fromToken;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
address payable beneficiary;
Utils.MegaSwapPath[] path;
address payable partner;
uint256 feePercent;
bytes permit;
uint256 deadline;
bytes16 uuid;
}
struct SimpleData {
address fromToken;
address toToken;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
address[] callees;
bytes exchangeData;
uint256[] startIndexes;
uint256[] values;
address payable beneficiary;
address payable partner;
uint256 feePercent;
bytes permit;
uint256 deadline;
bytes16 uuid;
}
struct DirectUniV3 {
address fromToken;
address toToken;
address exchange;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
uint256 feePercent;
uint256 deadline;
address payable partner;
bool isApproved;
address payable beneficiary;
bytes path;
bytes permit;
bytes16 uuid;
}
struct DirectCurveV1 {
address fromToken;
address toToken;
address exchange;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
uint256 feePercent;
int128 i;
int128 j;
address payable partner;
bool isApproved;
CurveSwapType swapType;
address payable beneficiary;
bool needWrapNative;
bytes permit;
bytes16 uuid;
}
struct DirectCurveV2 {
address fromToken;
address toToken;
address exchange;
address poolAddress;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
uint256 feePercent;
uint256 i;
uint256 j;
address payable partner;
bool isApproved;
CurveSwapType swapType;
address payable beneficiary;
bool needWrapNative;
bytes permit;
bytes16 uuid;
}
struct DirectBalancerV2 {
IBalancerV2Vault.BatchSwapStep[] swaps;
address[] assets;
IBalancerV2Vault.FundManagement funds;
int256[] limits;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
uint256 deadline;
uint256 feePercent;
address vault;
address payable partner;
bool isApproved;
address payable beneficiary;
bytes permit;
bytes16 uuid;
}
struct Adapter {
address payable adapter;
uint256 percent;
uint256 networkFee; //NOT USED
Route[] route;
}
struct Route {
uint256 index; //Adapter at which index needs to be used
address targetExchange;
uint256 percent;
bytes payload;
uint256 networkFee; //NOT USED - Network fee is associated with 0xv3 trades
}
struct MegaSwapPath {
uint256 fromAmountPercent;
Path[] path;
}
struct Path {
address to;
uint256 totalNetworkFee; //NOT USED - Network fee is associated with 0xv3 trades
Adapter[] adapters;
}
function ethAddress() internal pure returns (address) {
return ETH_ADDRESS;
}
function maxUint() internal pure returns (uint256) {
return MAX_UINT;
}
function approve(
address addressToApprove,
address token,
uint256 amount
) internal {
if (token != ETH_ADDRESS) {
IERC20 _token = IERC20(token);
uint256 allowance = _token.allowance(address(this), addressToApprove);
if (allowance < amount) {
_token.safeApprove(addressToApprove, 0);
_token.safeIncreaseAllowance(addressToApprove, MAX_UINT);
}
}
}
function transferTokens(
address token,
address payable destination,
uint256 amount
) internal {
if (amount > 0) {
if (token == ETH_ADDRESS) {
(bool result, ) = destination.call{ value: amount, gas: 10000 }("");
require(result, "Failed to transfer Ether");
} else {
IERC20(token).safeTransfer(destination, amount);
}
}
}
function tokenBalance(address token, address account) internal view returns (uint256) {
if (token == ETH_ADDRESS) {
return account.balance;
} else {
return IERC20(token).balanceOf(account);
}
}
function permit(address token, bytes memory permit) internal {
if (permit.length == 32 * 7) {
(bool success, ) = token.call(abi.encodePacked(IERC20Permit.permit.selector, permit));
require(success, "Permit failed");
}
if (permit.length == 32 * 8) {
(bool success, ) = token.call(abi.encodePacked(IERC20PermitLegacy.permit.selector, permit));
require(success, "Permit failed");
}
}
function transferETH(address payable destination, uint256 amount) internal {
if (amount > 0) {
(bool result, ) = destination.call{ value: amount, gas: 10000 }("");
require(result, "Transfer ETH failed");
}
}
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
abstract contract IWETH is IERC20 {
function deposit() external payable virtual;
function withdraw(uint256 amount) external virtual;
}// SPDX-License-Identifier: ISC
pragma solidity 0.7.5;
contract WethProvider {
/*solhint-disable var-name-mixedcase*/
address public immutable WETH;
/*solhint-enable var-name-mixedcase*/
constructor(address weth) public {
WETH = weth;
}
}{
"metadata": {
"bytecodeHash": "none",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint16","name":"aaveeRefCode","type":"uint16"},{"internalType":"address","name":"aaveeSpender","type":"address"},{"internalType":"address","name":"uniswapFactory","type":"address"},{"internalType":"address","name":"chai","type":"address"},{"internalType":"address","name":"dai","type":"address"},{"internalType":"address","name":"weth","type":"address"},{"internalType":"address","name":"stETH","type":"address"},{"internalType":"uint16","name":"_aaveV3RefCode","type":"uint16"},{"internalType":"address","name":"_aaveV3Pool","type":"address"},{"internalType":"address","name":"_aaveV3WethGateway","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"aaveV3Pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"aaveV3RefCode","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"aaveV3WethGateway","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chai","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dai","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refCodeV1","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"spender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"toToken","type":"address"},{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"targetExchange","type":"address"},{"internalType":"uint256","name":"percent","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"uint256","name":"networkFee","type":"uint256"}],"internalType":"struct Utils.Route[]","name":"route","type":"tuple[]"}],"name":"swap","outputs":[],"stateMutability":"payable","type":"function"}]Contract Creation Code
6101e06040523480156200001257600080fd5b5060405162005d2838038062005d288339810160408190526200003591620000e2565b6001600160601b0319606097881b811660805295871b861660a081905297871b861660c05293861b851660e0526001600160f01b031960f0998a1b81166101005297861b85166101205291851b841661014052610160959095529390951b9093166101805290811b82166101a0529190911b166101c052620001b0565b80516001600160a01b0381168114620000ca57600080fd5b919050565b805161ffff81168114620000ca57600080fd5b6000806000806000806000806000806101408b8d03121562000102578586fd5b6200010d8b620000cf565b99506200011d60208c01620000b2565b98506200012d60408c01620000b2565b97506200013d60608c01620000b2565b96506200014d60808c01620000b2565b95506200015d60a08c01620000b2565b94506200016d60c08c01620000b2565b93506200017d60e08c01620000cf565b92506200018e6101008c01620000b2565b91506200019f6101208c01620000b2565b90509295989b9194979a5092959850565b60805160601c60a05160601c60c05160601c60e05160601c6101005160f01c6101205160601c6101405160601c6101605160601c6101805160f01c6101a05160601c6101c05160601c615a31620002f76000398061032f52806139b05280613a135280613bde52508061027b5280613a405280613aa85280613b0b5280613c0d5280613c955280613cf85250806101f85280613c315280613d2b5250806118f75250806102e75280611772528061182c525080610bf452806134355250806102575280613782528061382f52508061029f5280610fbb52806110215280611080528061127a5280611b805280611c055280611d3e5280611e035280612d4e52806130f652508061030b5280613dd3525080610c18528061257a52806126e55250806102c352806124fe5280612526528061267f5280612739528061283e5250615a316000f3fe6080604052600436106100c75760003560e01c8063c1fe3e4811610074578063e76b146c1161004e578063e76b146c146101b9578063e8edc816146101cc578063f4b9fa75146101e1576100c7565b8063c1fe3e481461017a578063c45a01551461018f578063ca3817de146101a4576100c7565b806386a06ff0116100a557806386a06ff01461012e578063ad5c464814610150578063b69d045614610165576100c7565b80630c388735146100cc578063439fab91146100f75780636824c88b14610119575b600080fd5b3480156100d857600080fd5b506100e16101f6565b6040516100ee919061576e565b60405180910390f35b34801561010357600080fd5b50610117610112366004614a37565b61021a565b005b34801561012557600080fd5b506100e1610255565b34801561013a57600080fd5b50610143610279565b6040516100ee9190615172565b34801561015c57600080fd5b5061014361029d565b34801561017157600080fd5b506101436102c1565b34801561018657600080fd5b506101436102e5565b34801561019b57600080fd5b50610143610309565b3480156101b057600080fd5b5061014361032d565b6101176101c7366004614aa4565b610351565b3480156101d857600080fd5b50610143610bf2565b3480156101ed57600080fd5b50610143610c16565b7f000000000000000000000000000000000000000000000000000000000000000081565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906154fc565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60005b81811015610be95782828281811061036857fe5b905060200281019061037a91906158d9565b356103c6576103c187876103bc6127106103b688888881811061039957fe5b90506020028101906103ab91906158d9565b8b9060400135610c3a565b90610cb6565b610d37565b610be1565b8282828181106103d257fe5b90506020028101906103e491906158d9565b356001141561040c576103c187876104076127106103b688888881811061039957fe5b610d47565b82828281811061041857fe5b905060200281019061042a91906158d9565b35600214156104ad576103c1878761044d6127106103b688888881811061039957fe5b86868681811061045957fe5b905060200281019061046b91906158d9565b61047c90604081019060200161496f565b87878781811061048857fe5b905060200281019061049a91906158d9565b6104a890606081019061586f565b610d5a565b8282828181106104b957fe5b90506020028101906104cb91906158d9565b356003141561051f576103c187876104ee6127106103b688888881811061039957fe5b8686868181106104fa57fe5b905060200281019061050c91906158d9565b61051a90606081019061586f565b610e12565b82828281811061052b57fe5b905060200281019061053d91906158d9565b35600414156105c0576103c187876105606127106103b688888881811061039957fe5b86868681811061056c57fe5b905060200281019061057e91906158d9565b61058f90604081019060200161496f565b87878781811061059b57fe5b90506020028101906105ad91906158d9565b6105bb90606081019061586f565b610e5b565b8282828181106105cc57fe5b90506020028101906105de91906158d9565b3560051415610661576103c187876106016127106103b688888881811061039957fe5b86868681811061060d57fe5b905060200281019061061f91906158d9565b61063090604081019060200161496f565b87878781811061063c57fe5b905060200281019061064e91906158d9565b61065c90606081019061586f565b610f16565b82828281811061066d57fe5b905060200281019061067f91906158d9565b3560061415610702576103c187876106a26127106103b688888881811061039957fe5b8686868181106106ae57fe5b90506020028101906106c091906158d9565b6106d190604081019060200161496f565b8787878181106106dd57fe5b90506020028101906106ef91906158d9565b6106fd90606081019061586f565b610f61565b82828281811061070e57fe5b905060200281019061072091906158d9565b35600714156107a3576103c187876107436127106103b688888881811061039957fe5b86868681811061074f57fe5b905060200281019061076191906158d9565b61077290604081019060200161496f565b87878781811061077e57fe5b905060200281019061079091906158d9565b61079e90606081019061586f565b611361565b8282828181106107af57fe5b90506020028101906107c191906158d9565b3560081415610844576103c187876107e46127106103b688888881811061039957fe5b8686868181106107f057fe5b905060200281019061080291906158d9565b61081390604081019060200161496f565b87878781811061081f57fe5b905060200281019061083191906158d9565b61083f90606081019061586f565b6116cf565b82828281811061085057fe5b905060200281019061086291906158d9565b35600914156108e5576103c187876108856127106103b688888881811061039957fe5b86868681811061089157fe5b90506020028101906108a391906158d9565b6108b490604081019060200161496f565b8787878181106108c057fe5b90506020028101906108d291906158d9565b6108e090606081019061586f565b6118df565b8282828181106108f157fe5b905060200281019061090391906158d9565b35600a1415610986576103c187876109266127106103b688888881811061039957fe5b86868681811061093257fe5b905060200281019061094491906158d9565b61095590604081019060200161496f565b87878781811061096157fe5b905060200281019061097391906158d9565b61098190606081019061586f565b611a87565b82828281811061099257fe5b90506020028101906109a491906158d9565b35600b1415610a27576103c187876109c76127106103b688888881811061039957fe5b8686868181106109d357fe5b90506020028101906109e591906158d9565b6109f690604081019060200161496f565b878787818110610a0257fe5b9050602002810190610a1491906158d9565b610a2290606081019061586f565b611e74565b828282818110610a3357fe5b9050602002810190610a4591906158d9565b35600c1415610a9c576103c18787610a686127106103b688888881811061039957fe5b868686818110610a7457fe5b9050602002810190610a8691906158d9565b610a9790604081019060200161496f565b61200d565b828282818110610aa857fe5b9050602002810190610aba91906158d9565b35600d1415610b0e576103c18787610add6127106103b688888881811061039957fe5b868686818110610ae957fe5b9050602002810190610afb91906158d9565b610b0990606081019061586f565b61219e565b828282818110610b1a57fe5b9050602002810190610b2c91906158d9565b35600e1415610baf576103c18787610b4f6127106103b688888881811061039957fe5b868686818110610b5b57fe5b9050602002810190610b6d91906158d9565b610b7e90604081019060200161496f565b878787818110610b8a57fe5b9050602002810190610b9c91906158d9565b610baa90606081019061586f565b6121e0565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906155d8565b600101610354565b50505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600082610c4957506000610cb0565b82820282848281610c5657fe5b0414610cad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806159a46021913960400191505060405180910390fd5b90505b92915050565b6000808211610d2657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610d2f57fe5b049392505050565b610d428383836124f9565b505050565b610d5483838360016128ec565b50505050565b610d626144d7565b610d6e82840184614faf565b9050610d7b848887612b7b565b805160208201516040517f5673b02d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871692635673b02d92610dd7928a90600190600401615854565b600060405180830381600087803b158015610df157600080fd5b505af1158015610e05573d6000803e3d6000fd5b5050505050505050505050565b610e5485858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612cc292505050565b5050505050565b610e66838786612b7b565b604080517f6d9a640a0000000000000000000000000000000000000000000000000000000081526004810186905260016024820152306044820152905173ffffffffffffffffffffffffffffffffffffffff851691636d9a640a9160648083019260209291908290030181600087803b158015610ee257600080fd5b505af1158015610ef6573d6000803e3d6000fd5b505050506040513d6020811015610f0c57600080fd5b5050505050505050565b610f598686868686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061341292505050565b505050505050565b610f696144f1565b610f7582840184614e5a565b90506000610f8161388e565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614610fb95787610fdb565b7f00000000000000000000000000000000000000000000000000000000000000005b90506000610fe761388e565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161461101f5787611041565b7f00000000000000000000000000000000000000000000000000000000000000005b905061104b61388e565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415611100577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0886040518263ffffffff1660e01b81526004016000604051808303818588803b1580156110e657600080fd5b505af11580156110fa573d6000803e3d6000fd5b50505050505b61110b868389612b7b565b825160208401516040517fceb757d500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff89169263ceb757d59261118d928c92600192909130907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90600401615786565b600060405180830381600087803b1580156111a757600080fd5b505af11580156111bb573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261120191908101906149a7565b5061120a61388e565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415611356576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d9082906370a08231906112b7903090600401615172565b60206040518083038186803b1580156112cf57600080fd5b505afa1580156112e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113079190615060565b6040518263ffffffff1660e01b8152600401611323919061577d565b600060405180830381600087803b15801561133d57600080fd5b505af1158015611351573d6000803e3d6000fd5b505050505b505050505050505050565b61136961450b565b61137582840184614dc3565b9050611382848887612b7b565b80516114ae57611390614540565b6040518060c00160405280836020015173ffffffffffffffffffffffffffffffffffffffff1681526020016001815260200187815260200183606001516fffffffffffffffffffffffffffffffff1681526020018360a001516fffffffffffffffffffffffffffffffff1681526020013073ffffffffffffffffffffffffffffffffffffffff1681525090508473ffffffffffffffffffffffffffffffffffffffff16633bf8c173826040518263ffffffff1660e01b81526004016114559190615686565b6040805180830381600087803b15801561146e57600080fd5b505af1158015611482573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a69190615078565b505050610be9565b600181511415611585576114c0614540565b6040518060c00160405280836020015173ffffffffffffffffffffffffffffffffffffffff1681526020018781526020016001815260200183606001516fffffffffffffffffffffffffffffffff1681526020018360a001516fffffffffffffffffffffffffffffffff1681526020013073ffffffffffffffffffffffffffffffffffffffff1681525090508473ffffffffffffffffffffffffffffffffffffffff1663e6c3189a826040518263ffffffff1660e01b81526004016114559190615686565b60028151141561169d576115976145a2565b604051806101000160405280836020015173ffffffffffffffffffffffffffffffffffffffff168152602001836080015173ffffffffffffffffffffffffffffffffffffffff168152602001836040015173ffffffffffffffffffffffffffffffffffffffff1681526020018781526020016001815260200183606001516fffffffffffffffffffffffffffffffff1681526020018360a001516fffffffffffffffffffffffffffffffff1681526020013073ffffffffffffffffffffffffffffffffffffffff1681525090508473ffffffffffffffffffffffffffffffffffffffff1663c0034cfb826040518263ffffffff1660e01b8152600401611455919061560f565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c9061556a565b6116d761388e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161461177057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f737263546f6b656e2073686f756c642062652045544800000000000000000000604482015290519081900360640190fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161461182a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f64657374546f6b656e2073686f756c6420626520737445544800000000000000604482015290519081900360640190fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a1903eab8560006040518363ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506020604051808303818588803b1580156118b457600080fd5b505af11580156118c8573d6000803e3d6000fd5b50505050506040513d6020811015610f0c57600080fd5b6118e761463f565b6118f382840184614f54565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415611a2657600061198d61197b83604001516119758560200151670de0b6b3a76400006138a690919063ffffffff16565b90610c3a565b6103b688670de0b6b3a7640000610c3a565b905061199a858988612b7b565b6040517f8d7ef9bb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861690638d7ef9bb906119ee9030908590600401615193565b600060405180830381600087803b158015611a0857600080fd5b505af1158015611a1c573d6000803e3d6000fd5b5050505050610be9565b8051611a33908887612b7b565b6040517f9599127600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690639599127690610dd79030908990600401615193565b611a8f614676565b611a9b82840184614b66565b905060005b815151811015611b4257600082600001518281518110611abc57fe5b60209081029190910101515151905073ffffffffffffffffffffffffffffffffffffffff81161580611b03575073ffffffffffffffffffffffffffffffffffffffff811633145b611b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c90615533565b50600101611aa0565b50611b4b61388e565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415611c2f577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b158015611be657600080fd5b505af1158015611bfa573d6000803e3d6000fd5b5050505050611c2a847f000000000000000000000000000000000000000000000000000000000000000087612b7b565b611c3a565b611c3a848887612b7b565b80516040517f1c64b82000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861691631c64b82091611c91919089903090600401615244565b600060405180830381600087803b158015611cab57600080fd5b505af1158015611cbf573d6000803e3d6000fd5b50505050611ccb61388e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415610be9576040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190611d73903090600401615172565b60206040518083038186803b158015611d8b57600080fd5b505afa158015611d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc39190615060565b6040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90611e3890849060040161577d565b600060405180830381600087803b158015611e5257600080fd5b505af1158015611e66573d6000803e3d6000fd5b505050505050505050505050565b611e7c614689565b611e8882840184614ff7565b9050611e95848887612b7b565b606081015160000b611f5e576020810151604080830151835191517f44b3e92300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8816936344b3e92393611f069391928b9291906001906004016153c8565b602060405180830381600087803b158015611f2057600080fd5b505af1158015611f34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f589190615060565b50610be9565b602081015160408083015190517fee52a2f300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87169263ee52a2f392611fbb928a91906004016153b2565b602060405180830381600087803b158015611fd557600080fd5b505af1158015611fe9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0c9190615060565b73ffffffffffffffffffffffffffffffffffffffff818116848216811491861614818015612039575080155b8061204a575080801561204a575081155b6120b557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4f6e6520746f6b656e2073686f756c6420626520777374455448000000000000604482015290519081900360640190fd5b811561214b576120c6838786612b7b565b8273ffffffffffffffffffffffffffffffffffffffff1663ea598cb0856040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561211957600080fd5b505af115801561212d573d6000803e3d6000fd5b505050506040513d602081101561214357600080fd5b50610f599050565b8273ffffffffffffffffffffffffffffffffffffffff1663de0e9a3e856040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015610ee257600080fd5b610e5485858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061391a92505050565b6121e86146b0565b6121f482840184614ceb565b90506121fe61388e565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16141561239b578373ffffffffffffffffffffffffffffffffffffffff1663f02109298260600151604051806101a00160405280856000015173ffffffffffffffffffffffffffffffffffffffff168152602001856040015173ffffffffffffffffffffffffffffffffffffffff1681526020013073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff16815260200185606001518a116123205789612326565b85606001515b815260200185606001518152602001856080015181526020018560a0015181526020018560c0015181526020018560e0015181526020018561010001518152506040518363ffffffff1660e01b81526004016123829190615694565b6000604051808303818588803b158015611a0857600080fd5b6123aa84888360600151612b7b565b8373ffffffffffffffffffffffffffffffffffffffff1663f0210929604051806101a00160405280846000015173ffffffffffffffffffffffffffffffffffffffff168152602001846040015173ffffffffffffffffffffffffffffffffffffffff1681526020013073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff168152602001846020015173ffffffffffffffffffffffffffffffffffffffff16815260200184606001518911612497578861249d565b84606001515b815260200184606001518152602001846080015181526020018460a0015181526020018460c0015181526020018460e0015181526020018461010001518152506040518263ffffffff1660e01b8152600401610dd79190615694565b6125247f00000000000000000000000000000000000000000000000000000000000000008483612b7b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156126e3577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461263257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44657374696e6174696f6e20746f6b656e2073686f756c642062652064616900604482015290519081900360640190fd5b604080517fef693bed00000000000000000000000000000000000000000000000000000000815230600482015260248101839052905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163ef693bed91604480830192600092919082900301818387803b1580156126c657600080fd5b505af11580156126da573d6000803e3d6000fd5b50505050610d42565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612885577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146127f157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f44657374696e6174696f6e20746f6b656e2073686f756c642062652063686169604482015290519081900360640190fd5b604080517f3b4da69f00000000000000000000000000000000000000000000000000000000815230600482015260248101839052905173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691633b4da69f91604480830192600092919082900301818387803b1580156126c657600080fd5b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c69642066726f6d546f6b656e000000000000000000000000000000604482015290519081900360640190fd5b6000806128f98686613d8a565b9050612906818786612b7b565b600061291061388e565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614156129d2578173ffffffffffffffffffffffffffffffffffffffff1663f39b5b9b8686426040518463ffffffff1660e01b815260040180838152602001828152602001925050506020604051808303818588803b15801561299e57600080fd5b505af11580156129b2573d6000803e3d6000fd5b50505050506040513d60208110156129c957600080fd5b50519050612b6f565b6129da61388e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415612ab357604080517f95e3c50b0000000000000000000000000000000000000000000000000000000081526004810187905260248101869052426044820152905173ffffffffffffffffffffffffffffffffffffffff8416916395e3c50b9160648083019260209291908290030181600087803b158015612a8957600080fd5b505af1158015612a9d573d6000803e3d6000fd5b505050506040513d60208110156129c957600080fd5b604080517fddf7e1a700000000000000000000000000000000000000000000000000000000815260048101879052602481018690526001604482015242606482015273ffffffffffffffffffffffffffffffffffffffff888116608483015291519184169163ddf7e1a79160a4808201926020929091908290030181600087803b158015612b4057600080fd5b505af1158015612b54573d6000803e3d6000fd5b505050506040513d6020811015612b6a57600080fd5b505190505b9150505b949350505050565b73ffffffffffffffffffffffffffffffffffffffff821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610d42576040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152829060009073ffffffffffffffffffffffffffffffffffffffff83169063dd62ed3e90612c0590309089906004016151b9565b60206040518083038186803b158015612c1d57600080fd5b505afa158015612c31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c559190615060565b905082811015610e5457612c8173ffffffffffffffffffffffffffffffffffffffff8316866000613e8c565b610e5473ffffffffffffffffffffffffffffffffffffffff8316867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61401a565b612cca614741565b81806020019051810190612cde9190614b4b565b9050612cef81600001518685612b7b565b805173ffffffffffffffffffffffffffffffffffffffff8681169116141561309757612d1961388e565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415612f01577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1663797bf3856040518163ffffffff1660e01b815260040160206040518083038186803b158015612dcd57600080fd5b505afa158015612de1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e05919061498b565b73ffffffffffffffffffffffffffffffffffffffff1614612e52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906154c5565b80516040517f81a6b25000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906381a6b25090612ea99030908790600401615193565b602060405180830381600087803b158015612ec357600080fd5b505af1158015612ed7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612efb9190615060565b50613092565b8373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1663797bf3856040518163ffffffff1660e01b815260040160206040518083038186803b158015612f6257600080fd5b505afa158015612f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9a919061498b565b73ffffffffffffffffffffffffffffffffffffffff1614612fe7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906154c5565b80516040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639dc29fac9061303e9030908790600401615193565b602060405180830381600087803b15801561305857600080fd5b505af115801561306c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130909190615060565b505b610e54565b805173ffffffffffffffffffffffffffffffffffffffff858116911614156133e0576130c161388e565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614156132a3577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1663797bf3856040518163ffffffff1660e01b815260040160206040518083038186803b15801561317557600080fd5b505afa158015613189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ad919061498b565b73ffffffffffffffffffffffffffffffffffffffff16146131fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c90615457565b80516040517f8f6ede1f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690638f6ede1f908590613251903090600401615172565b6020604051808303818588803b15801561326a57600080fd5b505af115801561327e573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612efb9190615060565b8473ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1663797bf3856040518163ffffffff1660e01b815260040160206040518083038186803b15801561330457600080fd5b505afa158015613318573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061333c919061498b565b73ffffffffffffffffffffffffffffffffffffffff1614613389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c90615457565b80516040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906340c10f199061303e9030908790600401615193565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906155a1565b61341a614741565b8180602001905181019061342e9190614b4b565b905061345b7f00000000000000000000000000000000000000000000000000000000000000008786612b7b565b805173ffffffffffffffffffffffffffffffffffffffff878116911614156135ef578473ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff166389d1a0fc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156134de57600080fd5b505afa1580156134f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613516919061498b565b73ffffffffffffffffffffffffffffffffffffffff1614613563576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906154c5565b80516040517fdb006a7500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063db006a75906135b890879060040161577d565b600060405180830381600087803b1580156135d257600080fd5b505af11580156135e6573d6000803e3d6000fd5b50505050610f59565b805173ffffffffffffffffffffffffffffffffffffffff8681169116141561385c578573ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff166389d1a0fc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561367257600080fd5b505afa158015613686573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136aa919061498b565b73ffffffffffffffffffffffffffffffffffffffff16146136f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906154c5565b6136ff61388e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156137e1576040517fd2d0e06600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84169063d2d0e0669086906137aa908a9083907f000000000000000000000000000000000000000000000000000000000000000090600401615425565b6000604051808303818588803b1580156137c357600080fd5b505af11580156137d7573d6000803e3d6000fd5b5050505050613857565b6040517fd2d0e06600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84169063d2d0e066906135b890899088907f000000000000000000000000000000000000000000000000000000000000000090600401615425565b610f59565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c9061548e565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90565b600082820183811015610cad57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b613922614741565b818060200190518101906139369190614b4b565b9050806000015173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415613b445761397861388e565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415613aa3576139d67f00000000000000000000000000000000000000000000000000000000000000008685612b7b565b6040517f80500d2000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906380500d2090613a6c907f00000000000000000000000000000000000000000000000000000000000000009087903090600401615214565b600060405180830381600087803b158015613a8657600080fd5b505af1158015613a9a573d6000803e3d6000fd5b50505050613092565b613ace7f00000000000000000000000000000000000000000000000000000000000000008685612b7b565b6040517f69328dec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906369328dec9061303e90879087903090600401615214565b805173ffffffffffffffffffffffffffffffffffffffff8581169116141561385c57613b6e61388e565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415613c90576040517f474cf53d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063474cf53d908590613c59907f00000000000000000000000000000000000000000000000000000000000000009030907f0000000000000000000000000000000000000000000000000000000000000000906004016151e0565b6000604051808303818588803b158015613c7257600080fd5b505af1158015613c86573d6000803e3d6000fd5b5050505050613092565b613cbb7f00000000000000000000000000000000000000000000000000000000000000008685612b7b565b6040517f617ba03700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063617ba03790613d53908890879030907f0000000000000000000000000000000000000000000000000000000000000000906004016153eb565b600060405180830381600087803b158015613d6d57600080fd5b505af1158015613d81573d6000803e3d6000fd5b50505050610e54565b600080613d9561388e565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614613dcd5783613dcf565b825b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166306f2bf62826040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613e5857600080fd5b505afa158015613e6c573d6000803e3d6000fd5b505050506040513d6020811015613e8257600080fd5b5051949350505050565b801580613f385750604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015613f0a57600080fd5b505afa158015613f1e573d6000803e3d6000fd5b505050506040513d6020811015613f3457600080fd5b5051155b613f8d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806159ef6036913960400191505060405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052610d42908490614163565b60006140d7828573ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30876040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b1580156140a557600080fd5b505afa1580156140b9573d6000803e3d6000fd5b505050506040513d60208110156140cf57600080fd5b5051906138a6565b6040805173ffffffffffffffffffffffffffffffffffffffff8616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052909150610d549085905b60606141c5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661423b9092919063ffffffff16565b805190915015610d42578080602001905160208110156141e457600080fd5b5051610d42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806159c5602a913960400191505060405180910390fd5b606061424a8484600085614254565b90505b9392505050565b6060824710156142af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061597e6026913960400191505060405180910390fd5b6142b88561440f565b61432357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061438d57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614350565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146143ef576040519150601f19603f3d011682016040523d82523d6000602084013e6143f4565b606091505b5091509150614404828286614419565b979650505050505050565b803b15155b919050565b6060831561442857508161424d565b8251156144385782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561449c578181015183820152602001614484565b50505050905090810190601f1680156144c95780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b604051806040016040528060008152602001600081525090565b604051806040016040528060608152602001606081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b604051806101000160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081525090565b6040518060200160405280606081525090565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806101200160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081526020016000815260200160008019168152602001606081525090565b60408051602081019091526000815290565b803561441481615958565b600082601f83011261476e578081fd5b813561478161477c8261593a565b615916565b8181529150602080830190848101818402860182018710156147a257600080fd5b60005b848110156147ca5781356147b881615958565b845292820192908201906001016147a5565b505050505092915050565b600082601f8301126147e5578081fd5b813567ffffffffffffffff8111156147f957fe5b61482a60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601615916565b915080825283602082850101111561484157600080fd5b8060208401602084013760009082016020015292915050565b60006020828403121561486b578081fd5b6040516020810181811067ffffffffffffffff8211171561488857fe5b8060405250809150825161489b81615958565b905292915050565b60006101008083850312156148b6578182fd5b6040519081019067ffffffffffffffff821181831017156148d357fe5b81604052809250833581526148ea6020850161494f565b60208201526148fb60408501614753565b604082015261490c60608501614753565b606082015261491d60808501614753565b608082015261492e60a08501614753565b60a082015260c084013560c082015260e084013560e0820152505092915050565b80356fffffffffffffffffffffffffffffffff8116811461441457600080fd5b600060208284031215614980578081fd5b8135610cad81615958565b60006020828403121561499c578081fd5b8151610cad81615958565b600060208083850312156149b9578182fd5b825167ffffffffffffffff8111156149cf578283fd5b8301601f810185136149df578283fd5b80516149ed61477c8261593a565b8181528381019083850185840285018601891015614a09578687fd5b8694505b83851015614a2b578051835260019490940193918501918501614a0d565b50979650505050505050565b60008060208385031215614a49578081fd5b823567ffffffffffffffff80821115614a60578283fd5b818501915085601f830112614a73578283fd5b813581811115614a81578384fd5b866020828501011115614a92578384fd5b60209290920196919550909350505050565b60008060008060008060a08789031215614abc578182fd5b8635614ac781615958565b95506020870135614ad781615958565b94506040870135935060608701359250608087013567ffffffffffffffff80821115614b01578384fd5b818901915089601f830112614b14578384fd5b813581811115614b22578485fd5b8a60208083028501011115614b35578485fd5b6020830194508093505050509295509295509295565b600060208284031215614b5c578081fd5b61424d838361485a565b60006020808385031215614b78578182fd5b823567ffffffffffffffff80821115614b8f578384fd5b8185019150828287031215614ba2578384fd5b6040518381018181108382111715614bb657fe5b604052823582811115614bc7578586fd5b80840193505086601f840112614bdb578485fd5b8235614be961477c8261593a565b81815285810190858701885b84811015614cda57813588016101807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828f03011215614c33578a8bfd5b614c3d60a0615916565b614c498e8c84016148a3565b815261012082013589811115614c5d578c8dfd5b614c6b8f8d838601016147d5565b8c83015250610140820135604082015261016082013589811115614c8d578c8dfd5b614c9b8f8d838601016147d5565b60608301525061018082013589811115614cb3578c8dfd5b614cc18f8d838601016147d5565b6080830152508552509288019290880190600101614bf5565b505083525090979650505050505050565b600060208284031215614cfc578081fd5b813567ffffffffffffffff80821115614d13578283fd5b8184019150610120808387031215614d29578384fd5b614d3281615916565b9050614d3d83614753565b8152614d4b60208401614753565b6020820152614d5c60408401614753565b6040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e08201526101008084013583811115614da6578586fd5b614db2888287016147d5565b918301919091525095945050505050565b600060c08284031215614dd4578081fd5b60405160c0810181811067ffffffffffffffff82111715614df157fe5b604052823581526020830135614e0681615958565b60208201526040830135614e1981615958565b6040820152614e2a6060840161494f565b60608201526080830135614e3d81615958565b6080820152614e4e60a0840161494f565b60a08201529392505050565b60006020808385031215614e6c578182fd5b823567ffffffffffffffff80821115614e83578384fd5b9084019060408287031215614e96578384fd5b604051604081018181108382111715614eab57fe5b604052823582811115614ebc578586fd5b8301601f81018813614ecc578586fd5b8035614eda61477c8261593a565b81815286810190838801888402850189018c1015614ef657898afd5b8994505b83851015614f21578035614f0d81615958565b835260019490940193918801918801614efa565b5084525050508284013582811115614f37578586fd5b614f438882860161475e565b948201949094529695505050505050565b600060608284031215614f65578081fd5b6040516060810181811067ffffffffffffffff82111715614f8257fe5b6040528235614f9081615958565b8152602083810135908201526040928301359281019290925250919050565b600060408284031215614fc0578081fd5b6040516040810181811067ffffffffffffffff82111715614fdd57fe5b604052823581526020928301359281019290925250919050565b600060808284031215615008578081fd5b6040516080810181811067ffffffffffffffff8211171561502557fe5b8060405250823581526020830135602082015260408301356040820152606083013580830b8114615054578283fd5b60608201529392505050565b600060208284031215615071578081fd5b5051919050565b6000806040838503121561508a578182fd5b505080516020909101519092909150565b73ffffffffffffffffffffffffffffffffffffffff169052565b60008151808452815b818110156150da576020818501810151868301820152016150be565b818111156150eb5782602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b73ffffffffffffffffffffffffffffffffffffffff808251168352602082015160208401526040820151604084015260608201516060840152608082015160808401528060a08301511660a0840152505050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff938416815291909216602082015261ffff909116604082015260600190565b73ffffffffffffffffffffffffffffffffffffffff93841681526020810192909252909116604082015260600190565b606080825284518282018190526000919060809081850190602080820287018401818b01875b84811015615395577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808a840301865281516101808151805186526fffffffffffffffffffffffffffffffff87820151168787015260408082015173ffffffffffffffffffffffffffffffffffffffff808216838a0152808e850151168e8a015250508a8201516152fc8c89018261509b565b5060a08083015161530f828a018261509b565b505060c080830151818901525060e080830151818901525087840151915082610100880152615340838801836150b5565b92508084015161012088015250508982015185820361014087015261536582826150b5565b91505088820151915084810361016086015261538181836150b5565b97860197945050509083019060010161526a565b50508096505088818801525050505050612b73604083018461509b565b9283526020830191909152604082015260600190565b948552602085019390935260408401919091526060830152608082015260a00190565b73ffffffffffffffffffffffffffffffffffffffff948516815260208101939093529216604082015261ffff909116606082015260800190565b73ffffffffffffffffffffffffffffffffffffffff939093168352602083019190915261ffff16604082015260600190565b60208082526012908201527f496e76616c69642066726f6d20746f6b656e0000000000000000000000000000604082015260600190565b6020808252600e908201527f496e76616c69642061546f6b656e000000000000000000000000000000000000604082015260600190565b60208082526010908201527f496e76616c696420746f20746f6b656e00000000000000000000000000000000604082015260600190565b60208082526016908201527f4d4554484f44204e4f5420494d504c454d454e54454400000000000000000000604082015260600190565b60208082526011908201527f756e617574686f72697a65642075736572000000000000000000000000000000604082015260600190565b6020808252600e908201527f496e76616c6964206f7054797065000000000000000000000000000000000000604082015260600190565b60208082526014908201527f496e76616c696420746f6b656e20706169722121000000000000000000000000604082015260600190565b60208082526013908201527f496e646578206e6f7420737570706f7274656400000000000000000000000000604082015260600190565b60006101008201905073ffffffffffffffffffffffffffffffffffffffff808451168352806020850151166020840152806040850151166040840152606084015160608401526080840151608084015260a084015160a084015260c084015160c08401528060e08501511660e08401525092915050565b60c08101610cb0828461511e565b6000602082526156a860208301845161509b565b60208301516156ba604084018261509b565b5060408301516156cd606084018261509b565b5060608301516156e0608084018261509b565b5060808301516156f360a084018261509b565b5060a083015161570660c084018261509b565b5060c083015160e08381019190915283015161010080840191909152830151610120808401919091528301516101408084019190915283015161016080840191909152830151610180808401919091528301516101a080840152612b736101c08401826150b5565b61ffff91909116815260200190565b90815260200190565b600060c082018883526020888185015260c0604085015281885180845260e086019150828a019350845b818110156157e257845173ffffffffffffffffffffffffffffffffffffffff16835293830193918301916001016157b0565b505084810360608601528751808252908201925081880190845b8181101561582e57825173ffffffffffffffffffffffffffffffffffffffff16855293830193918301916001016157fc565b5050505080915050615843608083018561509b565b8260a0830152979650505050505050565b93845260208401929092526040830152606082015260800190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126158a3578283fd5b83018035915067ffffffffffffffff8211156158bd578283fd5b6020019150368190038213156158d257600080fd5b9250929050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261590c578182fd5b9190910192915050565b60405181810167ffffffffffffffff8111828210171561593257fe5b604052919050565b600067ffffffffffffffff82111561594e57fe5b5060209081020190565b73ffffffffffffffffffffffffffffffffffffffff8116811461597a57600080fd5b5056fe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a164736f6c6343000705000a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000003dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3000000000000000000000000c0a47dfe034b400b47bdad5fecda2621de6c4d9500000000000000000000000006af07097c9eeb7fd685c692751d5c66db49c2150000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84000000000000000000000000000000000000000000000000000000000000000100000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e2000000000000000000000000d322a49006fc828f9b5b37ab215f99b4e5cab19c
Deployed Bytecode
0x6080604052600436106100c75760003560e01c8063c1fe3e4811610074578063e76b146c1161004e578063e76b146c146101b9578063e8edc816146101cc578063f4b9fa75146101e1576100c7565b8063c1fe3e481461017a578063c45a01551461018f578063ca3817de146101a4576100c7565b806386a06ff0116100a557806386a06ff01461012e578063ad5c464814610150578063b69d045614610165576100c7565b80630c388735146100cc578063439fab91146100f75780636824c88b14610119575b600080fd5b3480156100d857600080fd5b506100e16101f6565b6040516100ee919061576e565b60405180910390f35b34801561010357600080fd5b50610117610112366004614a37565b61021a565b005b34801561012557600080fd5b506100e1610255565b34801561013a57600080fd5b50610143610279565b6040516100ee9190615172565b34801561015c57600080fd5b5061014361029d565b34801561017157600080fd5b506101436102c1565b34801561018657600080fd5b506101436102e5565b34801561019b57600080fd5b50610143610309565b3480156101b057600080fd5b5061014361032d565b6101176101c7366004614aa4565b610351565b3480156101d857600080fd5b50610143610bf2565b3480156101ed57600080fd5b50610143610c16565b7f000000000000000000000000000000000000000000000000000000000000000181565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906154fc565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000181565b7f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e281565b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b7f00000000000000000000000006af07097c9eeb7fd685c692751d5c66db49c21581565b7f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8481565b7f000000000000000000000000c0a47dfe034b400b47bdad5fecda2621de6c4d9581565b7f000000000000000000000000d322a49006fc828f9b5b37ab215f99b4e5cab19c81565b60005b81811015610be95782828281811061036857fe5b905060200281019061037a91906158d9565b356103c6576103c187876103bc6127106103b688888881811061039957fe5b90506020028101906103ab91906158d9565b8b9060400135610c3a565b90610cb6565b610d37565b610be1565b8282828181106103d257fe5b90506020028101906103e491906158d9565b356001141561040c576103c187876104076127106103b688888881811061039957fe5b610d47565b82828281811061041857fe5b905060200281019061042a91906158d9565b35600214156104ad576103c1878761044d6127106103b688888881811061039957fe5b86868681811061045957fe5b905060200281019061046b91906158d9565b61047c90604081019060200161496f565b87878781811061048857fe5b905060200281019061049a91906158d9565b6104a890606081019061586f565b610d5a565b8282828181106104b957fe5b90506020028101906104cb91906158d9565b356003141561051f576103c187876104ee6127106103b688888881811061039957fe5b8686868181106104fa57fe5b905060200281019061050c91906158d9565b61051a90606081019061586f565b610e12565b82828281811061052b57fe5b905060200281019061053d91906158d9565b35600414156105c0576103c187876105606127106103b688888881811061039957fe5b86868681811061056c57fe5b905060200281019061057e91906158d9565b61058f90604081019060200161496f565b87878781811061059b57fe5b90506020028101906105ad91906158d9565b6105bb90606081019061586f565b610e5b565b8282828181106105cc57fe5b90506020028101906105de91906158d9565b3560051415610661576103c187876106016127106103b688888881811061039957fe5b86868681811061060d57fe5b905060200281019061061f91906158d9565b61063090604081019060200161496f565b87878781811061063c57fe5b905060200281019061064e91906158d9565b61065c90606081019061586f565b610f16565b82828281811061066d57fe5b905060200281019061067f91906158d9565b3560061415610702576103c187876106a26127106103b688888881811061039957fe5b8686868181106106ae57fe5b90506020028101906106c091906158d9565b6106d190604081019060200161496f565b8787878181106106dd57fe5b90506020028101906106ef91906158d9565b6106fd90606081019061586f565b610f61565b82828281811061070e57fe5b905060200281019061072091906158d9565b35600714156107a3576103c187876107436127106103b688888881811061039957fe5b86868681811061074f57fe5b905060200281019061076191906158d9565b61077290604081019060200161496f565b87878781811061077e57fe5b905060200281019061079091906158d9565b61079e90606081019061586f565b611361565b8282828181106107af57fe5b90506020028101906107c191906158d9565b3560081415610844576103c187876107e46127106103b688888881811061039957fe5b8686868181106107f057fe5b905060200281019061080291906158d9565b61081390604081019060200161496f565b87878781811061081f57fe5b905060200281019061083191906158d9565b61083f90606081019061586f565b6116cf565b82828281811061085057fe5b905060200281019061086291906158d9565b35600914156108e5576103c187876108856127106103b688888881811061039957fe5b86868681811061089157fe5b90506020028101906108a391906158d9565b6108b490604081019060200161496f565b8787878181106108c057fe5b90506020028101906108d291906158d9565b6108e090606081019061586f565b6118df565b8282828181106108f157fe5b905060200281019061090391906158d9565b35600a1415610986576103c187876109266127106103b688888881811061039957fe5b86868681811061093257fe5b905060200281019061094491906158d9565b61095590604081019060200161496f565b87878781811061096157fe5b905060200281019061097391906158d9565b61098190606081019061586f565b611a87565b82828281811061099257fe5b90506020028101906109a491906158d9565b35600b1415610a27576103c187876109c76127106103b688888881811061039957fe5b8686868181106109d357fe5b90506020028101906109e591906158d9565b6109f690604081019060200161496f565b878787818110610a0257fe5b9050602002810190610a1491906158d9565b610a2290606081019061586f565b611e74565b828282818110610a3357fe5b9050602002810190610a4591906158d9565b35600c1415610a9c576103c18787610a686127106103b688888881811061039957fe5b868686818110610a7457fe5b9050602002810190610a8691906158d9565b610a9790604081019060200161496f565b61200d565b828282818110610aa857fe5b9050602002810190610aba91906158d9565b35600d1415610b0e576103c18787610add6127106103b688888881811061039957fe5b868686818110610ae957fe5b9050602002810190610afb91906158d9565b610b0990606081019061586f565b61219e565b828282818110610b1a57fe5b9050602002810190610b2c91906158d9565b35600e1415610baf576103c18787610b4f6127106103b688888881811061039957fe5b868686818110610b5b57fe5b9050602002810190610b6d91906158d9565b610b7e90604081019060200161496f565b878787818110610b8a57fe5b9050602002810190610b9c91906158d9565b610baa90606081019061586f565b6121e0565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906155d8565b600101610354565b50505050505050565b7f0000000000000000000000003dfd23a6c5e8bbcfc9581d2e864a68feb6a076d381565b7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f81565b600082610c4957506000610cb0565b82820282848281610c5657fe5b0414610cad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806159a46021913960400191505060405180910390fd5b90505b92915050565b6000808211610d2657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610d2f57fe5b049392505050565b610d428383836124f9565b505050565b610d5483838360016128ec565b50505050565b610d626144d7565b610d6e82840184614faf565b9050610d7b848887612b7b565b805160208201516040517f5673b02d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871692635673b02d92610dd7928a90600190600401615854565b600060405180830381600087803b158015610df157600080fd5b505af1158015610e05573d6000803e3d6000fd5b5050505050505050505050565b610e5485858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612cc292505050565b5050505050565b610e66838786612b7b565b604080517f6d9a640a0000000000000000000000000000000000000000000000000000000081526004810186905260016024820152306044820152905173ffffffffffffffffffffffffffffffffffffffff851691636d9a640a9160648083019260209291908290030181600087803b158015610ee257600080fd5b505af1158015610ef6573d6000803e3d6000fd5b505050506040513d6020811015610f0c57600080fd5b5050505050505050565b610f598686868686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061341292505050565b505050505050565b610f696144f1565b610f7582840184614e5a565b90506000610f8161388e565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614610fb95787610fdb565b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b90506000610fe761388e565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161461101f5787611041565b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b905061104b61388e565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415611100577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1663d0e30db0886040518263ffffffff1660e01b81526004016000604051808303818588803b1580156110e657600080fd5b505af11580156110fa573d6000803e3d6000fd5b50505050505b61110b868389612b7b565b825160208401516040517fceb757d500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff89169263ceb757d59261118d928c92600192909130907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90600401615786565b600060405180830381600087803b1580156111a757600080fd5b505af11580156111bb573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261120191908101906149a7565b5061120a61388e565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415611356576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21690632e1a7d4d9082906370a08231906112b7903090600401615172565b60206040518083038186803b1580156112cf57600080fd5b505afa1580156112e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113079190615060565b6040518263ffffffff1660e01b8152600401611323919061577d565b600060405180830381600087803b15801561133d57600080fd5b505af1158015611351573d6000803e3d6000fd5b505050505b505050505050505050565b61136961450b565b61137582840184614dc3565b9050611382848887612b7b565b80516114ae57611390614540565b6040518060c00160405280836020015173ffffffffffffffffffffffffffffffffffffffff1681526020016001815260200187815260200183606001516fffffffffffffffffffffffffffffffff1681526020018360a001516fffffffffffffffffffffffffffffffff1681526020013073ffffffffffffffffffffffffffffffffffffffff1681525090508473ffffffffffffffffffffffffffffffffffffffff16633bf8c173826040518263ffffffff1660e01b81526004016114559190615686565b6040805180830381600087803b15801561146e57600080fd5b505af1158015611482573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a69190615078565b505050610be9565b600181511415611585576114c0614540565b6040518060c00160405280836020015173ffffffffffffffffffffffffffffffffffffffff1681526020018781526020016001815260200183606001516fffffffffffffffffffffffffffffffff1681526020018360a001516fffffffffffffffffffffffffffffffff1681526020013073ffffffffffffffffffffffffffffffffffffffff1681525090508473ffffffffffffffffffffffffffffffffffffffff1663e6c3189a826040518263ffffffff1660e01b81526004016114559190615686565b60028151141561169d576115976145a2565b604051806101000160405280836020015173ffffffffffffffffffffffffffffffffffffffff168152602001836080015173ffffffffffffffffffffffffffffffffffffffff168152602001836040015173ffffffffffffffffffffffffffffffffffffffff1681526020018781526020016001815260200183606001516fffffffffffffffffffffffffffffffff1681526020018360a001516fffffffffffffffffffffffffffffffff1681526020013073ffffffffffffffffffffffffffffffffffffffff1681525090508473ffffffffffffffffffffffffffffffffffffffff1663c0034cfb826040518263ffffffff1660e01b8152600401611455919061560f565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c9061556a565b6116d761388e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161461177057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f737263546f6b656e2073686f756c642062652045544800000000000000000000604482015290519081900360640190fd5b7f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8473ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161461182a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f64657374546f6b656e2073686f756c6420626520737445544800000000000000604482015290519081900360640190fd5b7f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8473ffffffffffffffffffffffffffffffffffffffff1663a1903eab8560006040518363ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506020604051808303818588803b1580156118b457600080fd5b505af11580156118c8573d6000803e3d6000fd5b50505050506040513d6020811015610f0c57600080fd5b6118e761463f565b6118f382840184614f54565b90507f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415611a2657600061198d61197b83604001516119758560200151670de0b6b3a76400006138a690919063ffffffff16565b90610c3a565b6103b688670de0b6b3a7640000610c3a565b905061199a858988612b7b565b6040517f8d7ef9bb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861690638d7ef9bb906119ee9030908590600401615193565b600060405180830381600087803b158015611a0857600080fd5b505af1158015611a1c573d6000803e3d6000fd5b5050505050610be9565b8051611a33908887612b7b565b6040517f9599127600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690639599127690610dd79030908990600401615193565b611a8f614676565b611a9b82840184614b66565b905060005b815151811015611b4257600082600001518281518110611abc57fe5b60209081029190910101515151905073ffffffffffffffffffffffffffffffffffffffff81161580611b03575073ffffffffffffffffffffffffffffffffffffffff811633145b611b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c90615533565b50600101611aa0565b50611b4b61388e565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415611c2f577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b158015611be657600080fd5b505af1158015611bfa573d6000803e3d6000fd5b5050505050611c2a847f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc287612b7b565b611c3a565b611c3a848887612b7b565b80516040517f1c64b82000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861691631c64b82091611c91919089903090600401615244565b600060405180830381600087803b158015611cab57600080fd5b505af1158015611cbf573d6000803e3d6000fd5b50505050611ccb61388e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415610be9576040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216906370a0823190611d73903090600401615172565b60206040518083038186803b158015611d8b57600080fd5b505afa158015611d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc39190615060565b6040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21690632e1a7d4d90611e3890849060040161577d565b600060405180830381600087803b158015611e5257600080fd5b505af1158015611e66573d6000803e3d6000fd5b505050505050505050505050565b611e7c614689565b611e8882840184614ff7565b9050611e95848887612b7b565b606081015160000b611f5e576020810151604080830151835191517f44b3e92300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8816936344b3e92393611f069391928b9291906001906004016153c8565b602060405180830381600087803b158015611f2057600080fd5b505af1158015611f34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f589190615060565b50610be9565b602081015160408083015190517fee52a2f300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87169263ee52a2f392611fbb928a91906004016153b2565b602060405180830381600087803b158015611fd557600080fd5b505af1158015611fe9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0c9190615060565b73ffffffffffffffffffffffffffffffffffffffff818116848216811491861614818015612039575080155b8061204a575080801561204a575081155b6120b557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4f6e6520746f6b656e2073686f756c6420626520777374455448000000000000604482015290519081900360640190fd5b811561214b576120c6838786612b7b565b8273ffffffffffffffffffffffffffffffffffffffff1663ea598cb0856040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561211957600080fd5b505af115801561212d573d6000803e3d6000fd5b505050506040513d602081101561214357600080fd5b50610f599050565b8273ffffffffffffffffffffffffffffffffffffffff1663de0e9a3e856040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015610ee257600080fd5b610e5485858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061391a92505050565b6121e86146b0565b6121f482840184614ceb565b90506121fe61388e565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16141561239b578373ffffffffffffffffffffffffffffffffffffffff1663f02109298260600151604051806101a00160405280856000015173ffffffffffffffffffffffffffffffffffffffff168152602001856040015173ffffffffffffffffffffffffffffffffffffffff1681526020013073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff16815260200185606001518a116123205789612326565b85606001515b815260200185606001518152602001856080015181526020018560a0015181526020018560c0015181526020018560e0015181526020018561010001518152506040518363ffffffff1660e01b81526004016123829190615694565b6000604051808303818588803b158015611a0857600080fd5b6123aa84888360600151612b7b565b8373ffffffffffffffffffffffffffffffffffffffff1663f0210929604051806101a00160405280846000015173ffffffffffffffffffffffffffffffffffffffff168152602001846040015173ffffffffffffffffffffffffffffffffffffffff1681526020013073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff168152602001846020015173ffffffffffffffffffffffffffffffffffffffff16815260200184606001518911612497578861249d565b84606001515b815260200184606001518152602001846080015181526020018460a0015181526020018460c0015181526020018460e0015181526020018461010001518152506040518263ffffffff1660e01b8152600401610dd79190615694565b6125247f00000000000000000000000006af07097c9eeb7fd685c692751d5c66db49c2158483612b7b565b7f00000000000000000000000006af07097c9eeb7fd685c692751d5c66db49c21573ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156126e3577f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461263257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44657374696e6174696f6e20746f6b656e2073686f756c642062652064616900604482015290519081900360640190fd5b604080517fef693bed00000000000000000000000000000000000000000000000000000000815230600482015260248101839052905173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000006af07097c9eeb7fd685c692751d5c66db49c215169163ef693bed91604480830192600092919082900301818387803b1580156126c657600080fd5b505af11580156126da573d6000803e3d6000fd5b50505050610d42565b7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612885577f00000000000000000000000006af07097c9eeb7fd685c692751d5c66db49c21573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146127f157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f44657374696e6174696f6e20746f6b656e2073686f756c642062652063686169604482015290519081900360640190fd5b604080517f3b4da69f00000000000000000000000000000000000000000000000000000000815230600482015260248101839052905173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000006af07097c9eeb7fd685c692751d5c66db49c2151691633b4da69f91604480830192600092919082900301818387803b1580156126c657600080fd5b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c69642066726f6d546f6b656e000000000000000000000000000000604482015290519081900360640190fd5b6000806128f98686613d8a565b9050612906818786612b7b565b600061291061388e565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614156129d2578173ffffffffffffffffffffffffffffffffffffffff1663f39b5b9b8686426040518463ffffffff1660e01b815260040180838152602001828152602001925050506020604051808303818588803b15801561299e57600080fd5b505af11580156129b2573d6000803e3d6000fd5b50505050506040513d60208110156129c957600080fd5b50519050612b6f565b6129da61388e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415612ab357604080517f95e3c50b0000000000000000000000000000000000000000000000000000000081526004810187905260248101869052426044820152905173ffffffffffffffffffffffffffffffffffffffff8416916395e3c50b9160648083019260209291908290030181600087803b158015612a8957600080fd5b505af1158015612a9d573d6000803e3d6000fd5b505050506040513d60208110156129c957600080fd5b604080517fddf7e1a700000000000000000000000000000000000000000000000000000000815260048101879052602481018690526001604482015242606482015273ffffffffffffffffffffffffffffffffffffffff888116608483015291519184169163ddf7e1a79160a4808201926020929091908290030181600087803b158015612b4057600080fd5b505af1158015612b54573d6000803e3d6000fd5b505050506040513d6020811015612b6a57600080fd5b505190505b9150505b949350505050565b73ffffffffffffffffffffffffffffffffffffffff821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610d42576040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152829060009073ffffffffffffffffffffffffffffffffffffffff83169063dd62ed3e90612c0590309089906004016151b9565b60206040518083038186803b158015612c1d57600080fd5b505afa158015612c31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c559190615060565b905082811015610e5457612c8173ffffffffffffffffffffffffffffffffffffffff8316866000613e8c565b610e5473ffffffffffffffffffffffffffffffffffffffff8316867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61401a565b612cca614741565b81806020019051810190612cde9190614b4b565b9050612cef81600001518685612b7b565b805173ffffffffffffffffffffffffffffffffffffffff8681169116141561309757612d1961388e565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415612f01577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1663797bf3856040518163ffffffff1660e01b815260040160206040518083038186803b158015612dcd57600080fd5b505afa158015612de1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e05919061498b565b73ffffffffffffffffffffffffffffffffffffffff1614612e52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906154c5565b80516040517f81a6b25000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906381a6b25090612ea99030908790600401615193565b602060405180830381600087803b158015612ec357600080fd5b505af1158015612ed7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612efb9190615060565b50613092565b8373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1663797bf3856040518163ffffffff1660e01b815260040160206040518083038186803b158015612f6257600080fd5b505afa158015612f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9a919061498b565b73ffffffffffffffffffffffffffffffffffffffff1614612fe7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906154c5565b80516040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639dc29fac9061303e9030908790600401615193565b602060405180830381600087803b15801561305857600080fd5b505af115801561306c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130909190615060565b505b610e54565b805173ffffffffffffffffffffffffffffffffffffffff858116911614156133e0576130c161388e565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614156132a3577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1663797bf3856040518163ffffffff1660e01b815260040160206040518083038186803b15801561317557600080fd5b505afa158015613189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ad919061498b565b73ffffffffffffffffffffffffffffffffffffffff16146131fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c90615457565b80516040517f8f6ede1f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690638f6ede1f908590613251903090600401615172565b6020604051808303818588803b15801561326a57600080fd5b505af115801561327e573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612efb9190615060565b8473ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1663797bf3856040518163ffffffff1660e01b815260040160206040518083038186803b15801561330457600080fd5b505afa158015613318573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061333c919061498b565b73ffffffffffffffffffffffffffffffffffffffff1614613389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c90615457565b80516040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906340c10f199061303e9030908790600401615193565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906155a1565b61341a614741565b8180602001905181019061342e9190614b4b565b905061345b7f0000000000000000000000003dfd23a6c5e8bbcfc9581d2e864a68feb6a076d38786612b7b565b805173ffffffffffffffffffffffffffffffffffffffff878116911614156135ef578473ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff166389d1a0fc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156134de57600080fd5b505afa1580156134f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613516919061498b565b73ffffffffffffffffffffffffffffffffffffffff1614613563576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906154c5565b80516040517fdb006a7500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063db006a75906135b890879060040161577d565b600060405180830381600087803b1580156135d257600080fd5b505af11580156135e6573d6000803e3d6000fd5b50505050610f59565b805173ffffffffffffffffffffffffffffffffffffffff8681169116141561385c578573ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff166389d1a0fc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561367257600080fd5b505afa158015613686573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136aa919061498b565b73ffffffffffffffffffffffffffffffffffffffff16146136f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c906154c5565b6136ff61388e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156137e1576040517fd2d0e06600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84169063d2d0e0669086906137aa908a9083907f000000000000000000000000000000000000000000000000000000000000000190600401615425565b6000604051808303818588803b1580156137c357600080fd5b505af11580156137d7573d6000803e3d6000fd5b5050505050613857565b6040517fd2d0e06600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84169063d2d0e066906135b890899088907f000000000000000000000000000000000000000000000000000000000000000190600401615425565b610f59565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024c9061548e565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90565b600082820183811015610cad57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b613922614741565b818060200190518101906139369190614b4b565b9050806000015173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415613b445761397861388e565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415613aa3576139d67f000000000000000000000000d322a49006fc828f9b5b37ab215f99b4e5cab19c8685612b7b565b6040517f80500d2000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d322a49006fc828f9b5b37ab215f99b4e5cab19c16906380500d2090613a6c907f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e29087903090600401615214565b600060405180830381600087803b158015613a8657600080fd5b505af1158015613a9a573d6000803e3d6000fd5b50505050613092565b613ace7f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e28685612b7b565b6040517f69328dec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e216906369328dec9061303e90879087903090600401615214565b805173ffffffffffffffffffffffffffffffffffffffff8581169116141561385c57613b6e61388e565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415613c90576040517f474cf53d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d322a49006fc828f9b5b37ab215f99b4e5cab19c169063474cf53d908590613c59907f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e29030907f0000000000000000000000000000000000000000000000000000000000000001906004016151e0565b6000604051808303818588803b158015613c7257600080fd5b505af1158015613c86573d6000803e3d6000fd5b5050505050613092565b613cbb7f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e28685612b7b565b6040517f617ba03700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e2169063617ba03790613d53908890879030907f0000000000000000000000000000000000000000000000000000000000000001906004016153eb565b600060405180830381600087803b158015613d6d57600080fd5b505af1158015613d81573d6000803e3d6000fd5b50505050610e54565b600080613d9561388e565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614613dcd5783613dcf565b825b90507f000000000000000000000000c0a47dfe034b400b47bdad5fecda2621de6c4d9573ffffffffffffffffffffffffffffffffffffffff166306f2bf62826040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613e5857600080fd5b505afa158015613e6c573d6000803e3d6000fd5b505050506040513d6020811015613e8257600080fd5b5051949350505050565b801580613f385750604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015613f0a57600080fd5b505afa158015613f1e573d6000803e3d6000fd5b505050506040513d6020811015613f3457600080fd5b5051155b613f8d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806159ef6036913960400191505060405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052610d42908490614163565b60006140d7828573ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30876040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b1580156140a557600080fd5b505afa1580156140b9573d6000803e3d6000fd5b505050506040513d60208110156140cf57600080fd5b5051906138a6565b6040805173ffffffffffffffffffffffffffffffffffffffff8616602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052909150610d549085905b60606141c5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661423b9092919063ffffffff16565b805190915015610d42578080602001905160208110156141e457600080fd5b5051610d42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806159c5602a913960400191505060405180910390fd5b606061424a8484600085614254565b90505b9392505050565b6060824710156142af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061597e6026913960400191505060405180910390fd5b6142b88561440f565b61432357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061438d57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614350565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146143ef576040519150601f19603f3d011682016040523d82523d6000602084013e6143f4565b606091505b5091509150614404828286614419565b979650505050505050565b803b15155b919050565b6060831561442857508161424d565b8251156144385782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561449c578181015183820152602001614484565b50505050905090810190601f1680156144c95780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b604051806040016040528060008152602001600081525090565b604051806040016040528060608152602001606081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b604051806101000160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081525090565b6040518060200160405280606081525090565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806101200160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081526020016000815260200160008019168152602001606081525090565b60408051602081019091526000815290565b803561441481615958565b600082601f83011261476e578081fd5b813561478161477c8261593a565b615916565b8181529150602080830190848101818402860182018710156147a257600080fd5b60005b848110156147ca5781356147b881615958565b845292820192908201906001016147a5565b505050505092915050565b600082601f8301126147e5578081fd5b813567ffffffffffffffff8111156147f957fe5b61482a60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601615916565b915080825283602082850101111561484157600080fd5b8060208401602084013760009082016020015292915050565b60006020828403121561486b578081fd5b6040516020810181811067ffffffffffffffff8211171561488857fe5b8060405250809150825161489b81615958565b905292915050565b60006101008083850312156148b6578182fd5b6040519081019067ffffffffffffffff821181831017156148d357fe5b81604052809250833581526148ea6020850161494f565b60208201526148fb60408501614753565b604082015261490c60608501614753565b606082015261491d60808501614753565b608082015261492e60a08501614753565b60a082015260c084013560c082015260e084013560e0820152505092915050565b80356fffffffffffffffffffffffffffffffff8116811461441457600080fd5b600060208284031215614980578081fd5b8135610cad81615958565b60006020828403121561499c578081fd5b8151610cad81615958565b600060208083850312156149b9578182fd5b825167ffffffffffffffff8111156149cf578283fd5b8301601f810185136149df578283fd5b80516149ed61477c8261593a565b8181528381019083850185840285018601891015614a09578687fd5b8694505b83851015614a2b578051835260019490940193918501918501614a0d565b50979650505050505050565b60008060208385031215614a49578081fd5b823567ffffffffffffffff80821115614a60578283fd5b818501915085601f830112614a73578283fd5b813581811115614a81578384fd5b866020828501011115614a92578384fd5b60209290920196919550909350505050565b60008060008060008060a08789031215614abc578182fd5b8635614ac781615958565b95506020870135614ad781615958565b94506040870135935060608701359250608087013567ffffffffffffffff80821115614b01578384fd5b818901915089601f830112614b14578384fd5b813581811115614b22578485fd5b8a60208083028501011115614b35578485fd5b6020830194508093505050509295509295509295565b600060208284031215614b5c578081fd5b61424d838361485a565b60006020808385031215614b78578182fd5b823567ffffffffffffffff80821115614b8f578384fd5b8185019150828287031215614ba2578384fd5b6040518381018181108382111715614bb657fe5b604052823582811115614bc7578586fd5b80840193505086601f840112614bdb578485fd5b8235614be961477c8261593a565b81815285810190858701885b84811015614cda57813588016101807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828f03011215614c33578a8bfd5b614c3d60a0615916565b614c498e8c84016148a3565b815261012082013589811115614c5d578c8dfd5b614c6b8f8d838601016147d5565b8c83015250610140820135604082015261016082013589811115614c8d578c8dfd5b614c9b8f8d838601016147d5565b60608301525061018082013589811115614cb3578c8dfd5b614cc18f8d838601016147d5565b6080830152508552509288019290880190600101614bf5565b505083525090979650505050505050565b600060208284031215614cfc578081fd5b813567ffffffffffffffff80821115614d13578283fd5b8184019150610120808387031215614d29578384fd5b614d3281615916565b9050614d3d83614753565b8152614d4b60208401614753565b6020820152614d5c60408401614753565b6040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e08201526101008084013583811115614da6578586fd5b614db2888287016147d5565b918301919091525095945050505050565b600060c08284031215614dd4578081fd5b60405160c0810181811067ffffffffffffffff82111715614df157fe5b604052823581526020830135614e0681615958565b60208201526040830135614e1981615958565b6040820152614e2a6060840161494f565b60608201526080830135614e3d81615958565b6080820152614e4e60a0840161494f565b60a08201529392505050565b60006020808385031215614e6c578182fd5b823567ffffffffffffffff80821115614e83578384fd5b9084019060408287031215614e96578384fd5b604051604081018181108382111715614eab57fe5b604052823582811115614ebc578586fd5b8301601f81018813614ecc578586fd5b8035614eda61477c8261593a565b81815286810190838801888402850189018c1015614ef657898afd5b8994505b83851015614f21578035614f0d81615958565b835260019490940193918801918801614efa565b5084525050508284013582811115614f37578586fd5b614f438882860161475e565b948201949094529695505050505050565b600060608284031215614f65578081fd5b6040516060810181811067ffffffffffffffff82111715614f8257fe5b6040528235614f9081615958565b8152602083810135908201526040928301359281019290925250919050565b600060408284031215614fc0578081fd5b6040516040810181811067ffffffffffffffff82111715614fdd57fe5b604052823581526020928301359281019290925250919050565b600060808284031215615008578081fd5b6040516080810181811067ffffffffffffffff8211171561502557fe5b8060405250823581526020830135602082015260408301356040820152606083013580830b8114615054578283fd5b60608201529392505050565b600060208284031215615071578081fd5b5051919050565b6000806040838503121561508a578182fd5b505080516020909101519092909150565b73ffffffffffffffffffffffffffffffffffffffff169052565b60008151808452815b818110156150da576020818501810151868301820152016150be565b818111156150eb5782602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b73ffffffffffffffffffffffffffffffffffffffff808251168352602082015160208401526040820151604084015260608201516060840152608082015160808401528060a08301511660a0840152505050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff938416815291909216602082015261ffff909116604082015260600190565b73ffffffffffffffffffffffffffffffffffffffff93841681526020810192909252909116604082015260600190565b606080825284518282018190526000919060809081850190602080820287018401818b01875b84811015615395577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808a840301865281516101808151805186526fffffffffffffffffffffffffffffffff87820151168787015260408082015173ffffffffffffffffffffffffffffffffffffffff808216838a0152808e850151168e8a015250508a8201516152fc8c89018261509b565b5060a08083015161530f828a018261509b565b505060c080830151818901525060e080830151818901525087840151915082610100880152615340838801836150b5565b92508084015161012088015250508982015185820361014087015261536582826150b5565b91505088820151915084810361016086015261538181836150b5565b97860197945050509083019060010161526a565b50508096505088818801525050505050612b73604083018461509b565b9283526020830191909152604082015260600190565b948552602085019390935260408401919091526060830152608082015260a00190565b73ffffffffffffffffffffffffffffffffffffffff948516815260208101939093529216604082015261ffff909116606082015260800190565b73ffffffffffffffffffffffffffffffffffffffff939093168352602083019190915261ffff16604082015260600190565b60208082526012908201527f496e76616c69642066726f6d20746f6b656e0000000000000000000000000000604082015260600190565b6020808252600e908201527f496e76616c69642061546f6b656e000000000000000000000000000000000000604082015260600190565b60208082526010908201527f496e76616c696420746f20746f6b656e00000000000000000000000000000000604082015260600190565b60208082526016908201527f4d4554484f44204e4f5420494d504c454d454e54454400000000000000000000604082015260600190565b60208082526011908201527f756e617574686f72697a65642075736572000000000000000000000000000000604082015260600190565b6020808252600e908201527f496e76616c6964206f7054797065000000000000000000000000000000000000604082015260600190565b60208082526014908201527f496e76616c696420746f6b656e20706169722121000000000000000000000000604082015260600190565b60208082526013908201527f496e646578206e6f7420737570706f7274656400000000000000000000000000604082015260600190565b60006101008201905073ffffffffffffffffffffffffffffffffffffffff808451168352806020850151166020840152806040850151166040840152606084015160608401526080840151608084015260a084015160a084015260c084015160c08401528060e08501511660e08401525092915050565b60c08101610cb0828461511e565b6000602082526156a860208301845161509b565b60208301516156ba604084018261509b565b5060408301516156cd606084018261509b565b5060608301516156e0608084018261509b565b5060808301516156f360a084018261509b565b5060a083015161570660c084018261509b565b5060c083015160e08381019190915283015161010080840191909152830151610120808401919091528301516101408084019190915283015161016080840191909152830151610180808401919091528301516101a080840152612b736101c08401826150b5565b61ffff91909116815260200190565b90815260200190565b600060c082018883526020888185015260c0604085015281885180845260e086019150828a019350845b818110156157e257845173ffffffffffffffffffffffffffffffffffffffff16835293830193918301916001016157b0565b505084810360608601528751808252908201925081880190845b8181101561582e57825173ffffffffffffffffffffffffffffffffffffffff16855293830193918301916001016157fc565b5050505080915050615843608083018561509b565b8260a0830152979650505050505050565b93845260208401929092526040830152606082015260800190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126158a3578283fd5b83018035915067ffffffffffffffff8211156158bd578283fd5b6020019150368190038213156158d257600080fd5b9250929050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261590c578182fd5b9190910192915050565b60405181810167ffffffffffffffff8111828210171561593257fe5b604052919050565b600067ffffffffffffffff82111561594e57fe5b5060209081020190565b73ffffffffffffffffffffffffffffffffffffffff8116811461597a57600080fd5b5056fe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a164736f6c6343000705000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000010000000000000000000000003dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3000000000000000000000000c0a47dfe034b400b47bdad5fecda2621de6c4d9500000000000000000000000006af07097c9eeb7fd685c692751d5c66db49c2150000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84000000000000000000000000000000000000000000000000000000000000000100000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e2000000000000000000000000d322a49006fc828f9b5b37ab215f99b4e5cab19c
-----Decoded View---------------
Arg [0] : aaveeRefCode (uint16): 1
Arg [1] : aaveeSpender (address): 0x3dfd23A6c5E8BbcFc9581d2E864a68feb6a076d3
Arg [2] : uniswapFactory (address): 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95
Arg [3] : chai (address): 0x06AF07097C9Eeb7fD685c692751D5C66dB49c215
Arg [4] : dai (address): 0x6B175474E89094C44Da98b954EedeAC495271d0F
Arg [5] : weth (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [6] : stETH (address): 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84
Arg [7] : _aaveV3RefCode (uint16): 1
Arg [8] : _aaveV3Pool (address): 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2
Arg [9] : _aaveV3WethGateway (address): 0xD322A49006FC828F9B5B37Ab215F99B4E5caB19C
-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [1] : 0000000000000000000000003dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3
Arg [2] : 000000000000000000000000c0a47dfe034b400b47bdad5fecda2621de6c4d95
Arg [3] : 00000000000000000000000006af07097c9eeb7fd685c692751d5c66db49c215
Arg [4] : 0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f
Arg [5] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [6] : 000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [8] : 00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e2
Arg [9] : 000000000000000000000000d322a49006fc828f9b5b37ab215f99b4e5cab19c
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
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.