More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
39707701 | 47 mins ago | 4.5295388 xDAI | ||||
39707701 | 47 mins ago | 4.5295388 xDAI | ||||
39706307 | 2 hrs ago | 0.001 xDAI | ||||
39706307 | 2 hrs ago | 0.001 xDAI | ||||
39705956 | 3 hrs ago | 298.41259508 xDAI | ||||
39705956 | 3 hrs ago | 298.41259508 xDAI | ||||
39705914 | 3 hrs ago | 0.57999799 xDAI | ||||
39705914 | 3 hrs ago | 0.57999799 xDAI | ||||
39705837 | 3 hrs ago | 600 xDAI | ||||
39705837 | 3 hrs ago | 600 xDAI | ||||
39705834 | 3 hrs ago | 3 xDAI | ||||
39705834 | 3 hrs ago | 3 xDAI | ||||
39705176 | 4 hrs ago | 0.38600362 xDAI | ||||
39705176 | 4 hrs ago | 0.38600362 xDAI | ||||
39704953 | 4 hrs ago | 0.02862803 xDAI | ||||
39704953 | 4 hrs ago | 0.02862803 xDAI | ||||
39704851 | 4 hrs ago | 2.17339749 xDAI | ||||
39704851 | 4 hrs ago | 2.17339749 xDAI | ||||
39704693 | 5 hrs ago | 1.9 xDAI | ||||
39704693 | 5 hrs ago | 1.9 xDAI | ||||
39704537 | 5 hrs ago | 0.02847561 xDAI | ||||
39704537 | 5 hrs ago | 0.02847561 xDAI | ||||
39704425 | 5 hrs ago | 3.00036581 xDAI | ||||
39704425 | 5 hrs ago | 3.00036581 xDAI | ||||
39704403 | 5 hrs ago | 0.0001 xDAI |
Loading...
Loading
Contract Name:
LiFiDEXAggregator
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity)
/** *Submitted for verification at gnosisscan.io on 2024-10-03 */ pragma solidity ^0.8.0 ^0.8.1 ^0.8.17; // lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool); } // lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // lib/openzeppelin-contracts/contracts/utils/Address.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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://consensys.net/diligence/blog/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.8.0/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"); (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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } // lib/openzeppelin-contracts/contracts/utils/Context.sol // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // lib/openzeppelin-contracts/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.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 Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ 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' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to * 0 before setting it to a non-zero value. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } } // src/Periphery/LiFiDEXAggregator.sol address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001; address constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000; uint8 constant LOCKED = 2; uint8 constant NOT_LOCKED = 1; uint8 constant PAUSED = 2; uint8 constant NOT_PAUSED = 1; /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK) uint160 constant MIN_SQRT_RATIO = 4295128739; /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK) uint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342; /// @title LiFi DEX Aggregator /// @author Ilya Lyalin (contract copied from: https://github.com/sushiswap/sushiswap/blob/c8c80dec821003eb72eb77c7e0446ddde8ca9e1e/protocols/route-processor/contracts/RouteProcessor4.sol) /// @notice Processes calldata to swap using various DEXs /// @custom:version 1.0.0 contract LiFiDEXAggregator is Ownable { using SafeERC20 for IERC20; using Approve for IERC20; using SafeERC20 for IERC20Permit; using InputStream for uint256; event Route( address indexed from, address to, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOutMin, uint256 amountOut ); error MinimalOutputBalanceViolation(uint256 amountOut); IBentoBoxMinimal public immutable bentoBox; mapping(address => bool) public priviledgedUsers; address private lastCalledPool; uint8 private unlocked = NOT_LOCKED; uint8 private paused = NOT_PAUSED; modifier lock() { require(unlocked == NOT_LOCKED, "RouteProcessor is locked"); require(paused == NOT_PAUSED, "RouteProcessor is paused"); unlocked = LOCKED; _; unlocked = NOT_LOCKED; } modifier onlyOwnerOrPriviledgedUser() { require( msg.sender == owner() || priviledgedUsers[msg.sender], "RP: caller is not the owner or a privileged user" ); _; } constructor(address _bentoBox, address[] memory priviledgedUserList) { bentoBox = IBentoBoxMinimal(_bentoBox); lastCalledPool = IMPOSSIBLE_POOL_ADDRESS; for (uint256 i = 0; i < priviledgedUserList.length; i++) { priviledgedUsers[priviledgedUserList[i]] = true; } } function setPriviledge(address user, bool priviledge) external onlyOwner { priviledgedUsers[user] = priviledge; } function pause() external onlyOwnerOrPriviledgedUser { paused = PAUSED; } function resume() external onlyOwnerOrPriviledgedUser { paused = NOT_PAUSED; } /// @notice For native unwrapping receive() external payable {} /// @notice Processes the route generated off-chain. Has a lock /// @param tokenIn Address of the input token /// @param amountIn Amount of the input token /// @param tokenOut Address of the output token /// @param amountOutMin Minimum amount of the output token /// @return amountOut Actual amount of the output token function processRoute( address tokenIn, uint256 amountIn, address tokenOut, uint256 amountOutMin, address to, bytes memory route ) external payable lock returns (uint256 amountOut) { return processRouteInternal( tokenIn, amountIn, tokenOut, amountOutMin, to, route ); } /// @notice Transfers some value to <transferValueTo> and then processes the route /// @param transferValueTo Address where the value should be transferred /// @param amountValueTransfer How much value to transfer /// @param tokenIn Address of the input token /// @param amountIn Amount of the input token /// @param tokenOut Address of the output token /// @param amountOutMin Minimum amount of the output token /// @return amountOut Actual amount of the output token function transferValueAndprocessRoute( address payable transferValueTo, uint256 amountValueTransfer, address tokenIn, uint256 amountIn, address tokenOut, uint256 amountOutMin, address to, bytes memory route ) external payable lock returns (uint256 amountOut) { (bool success, bytes memory returnBytes) = transferValueTo.call{ value: amountValueTransfer }(""); if (!success) { assembly { revert(add(32, returnBytes), mload(returnBytes)) } } return processRouteInternal( tokenIn, amountIn, tokenOut, amountOutMin, to, route ); } /// @notice Processes the route generated off-chain /// @param tokenIn Address of the input token /// @param amountIn Amount of the input token /// @param tokenOut Address of the output token /// @param amountOutMin Minimum amount of the output token /// @return amountOut Actual amount of the output token function processRouteInternal( address tokenIn, uint256 amountIn, address tokenOut, uint256 amountOutMin, address to, bytes memory route ) private returns (uint256 amountOut) { uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? 0 : IERC20(tokenIn).balanceOf(msg.sender); uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to); uint256 realAmountIn = amountIn; { uint256 step = 0; uint256 stream = InputStream.createStream(route); while (stream.isNotEmpty()) { uint8 commandCode = stream.readUint8(); if (commandCode == 1) { uint256 usedAmount = processMyERC20(stream); if (step == 0) realAmountIn = usedAmount; } else if (commandCode == 2) processUserERC20(stream, amountIn); else if (commandCode == 3) { uint256 usedAmount = processNative(stream); if (step == 0) realAmountIn = usedAmount; } else if (commandCode == 4) processOnePool(stream); else if (commandCode == 5) processInsideBento(stream); else if (commandCode == 6) applyPermit(tokenIn, stream); else revert("RouteProcessor: Unknown command code"); ++step; } } uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? 0 : IERC20(tokenIn).balanceOf(msg.sender); require( balanceInFinal + amountIn >= balanceInInitial, "RouteProcessor: Minimal input balance violation" ); uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to); if (balanceOutFinal < balanceOutInitial + amountOutMin) revert MinimalOutputBalanceViolation( balanceOutFinal - balanceOutInitial ); amountOut = balanceOutFinal - balanceOutInitial; emit Route( msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut ); } /// @notice Applies ERC-2612 permit /// @param tokenIn permitted token /// @param stream Streamed program function applyPermit(address tokenIn, uint256 stream) private { uint256 value = stream.readUint(); uint256 deadline = stream.readUint(); uint8 v = stream.readUint8(); bytes32 r = stream.readBytes32(); bytes32 s = stream.readBytes32(); IERC20Permit(tokenIn).safePermit( msg.sender, address(this), value, deadline, v, r, s ); } /// @notice Processes native coin: call swap for all pools that swap from native coin /// @param stream Streamed program function processNative( uint256 stream ) private returns (uint256 amountTotal) { amountTotal = address(this).balance; distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal); } /// @notice Processes ERC20 token from this contract balance: /// @notice Call swap for all pools that swap from this token /// @param stream Streamed program function processMyERC20( uint256 stream ) private returns (uint256 amountTotal) { address token = stream.readAddress(); amountTotal = IERC20(token).balanceOf(address(this)); unchecked { if (amountTotal > 0) amountTotal -= 1; // slot undrain protection } distributeAndSwap(stream, address(this), token, amountTotal); } /// @notice Processes ERC20 token from msg.sender balance: /// @notice Call swap for all pools that swap from this token /// @param stream Streamed program /// @param amountTotal Amount of tokens to take from msg.sender function processUserERC20(uint256 stream, uint256 amountTotal) private { address token = stream.readAddress(); distributeAndSwap(stream, msg.sender, token, amountTotal); } /// @notice Processes ERC20 token for cases when the token has only one output pool /// @notice In this case liquidity is already at pool balance. This is an optimization /// @notice Call swap for all pools that swap from this token /// @param stream Streamed program function processOnePool(uint256 stream) private { address token = stream.readAddress(); swap(stream, INTERNAL_INPUT_SOURCE, token, 0); } /// @notice Processes Bento tokens /// @notice Call swap for all pools that swap from this token /// @param stream Streamed program function processInsideBento(uint256 stream) private { address token = stream.readAddress(); uint256 amountTotal = bentoBox.balanceOf(token, address(this)); unchecked { if (amountTotal > 0) amountTotal -= 1; // slot undrain protection } distributeAndSwap(stream, address(this), token, amountTotal); } /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool /// @param stream Streamed program /// @param from Where to take liquidity for swap /// @param tokenIn Input token /// @param amountTotal Total amount of tokenIn for swaps function distributeAndSwap( uint256 stream, address from, address tokenIn, uint256 amountTotal ) private { uint8 num = stream.readUint8(); unchecked { for (uint256 i = 0; i < num; ++i) { uint16 share = stream.readUint16(); uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/; amountTotal -= amount; swap(stream, from, tokenIn, amount); } } } /// @notice Makes swap /// @param stream Streamed program /// @param from Where to take liquidity for swap /// @param tokenIn Input token /// @param amountIn Amount of tokenIn to take for swap function swap( uint256 stream, address from, address tokenIn, uint256 amountIn ) private { uint8 poolType = stream.readUint8(); if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn); else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn); else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn); else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn); else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn); else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn); else revert("RouteProcessor: Unknown pool type"); } /// @notice Wraps/unwraps native token /// @param stream [direction & fake, recipient, wrapToken?] /// @param from Where to take liquidity for swap /// @param tokenIn Input token /// @param amountIn Amount of tokenIn to take for swap function wrapNative( uint256 stream, address from, address tokenIn, uint256 amountIn ) private { uint8 directionAndFake = stream.readUint8(); address to = stream.readAddress(); if (directionAndFake & 1 == 1) { // wrap native address wrapToken = stream.readAddress(); if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{ value: amountIn }(); if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn); } else { // unwrap native if (directionAndFake & 2 == 0) { if (from == msg.sender) IERC20(tokenIn).safeTransferFrom( msg.sender, address(this), amountIn ); IWETH(tokenIn).withdraw(amountIn); } (bool success, ) = payable(to).call{ value: amountIn }(""); require( success, "RouteProcessor.wrapNative: Native token transfer failed" ); } } /// @notice Bridge/unbridge tokens to/from Bento /// @param stream [direction, recipient] /// @param from Where to take liquidity for swap /// @param tokenIn Input token /// @param amountIn Amount of tokenIn to take for swap function bentoBridge( uint256 stream, address from, address tokenIn, uint256 amountIn ) private { uint8 direction = stream.readUint8(); address to = stream.readAddress(); if (direction > 0) { // outside to Bento // deposit to arbitrary recipient is possible only from address(bentoBox) if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn); else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom( msg.sender, address(bentoBox), amountIn ); else { // tokens already are at address(bentoBox) amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) + bentoBox.strategyData(tokenIn).balance - bentoBox.totals(tokenIn).elastic; } bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0); } else { // Bento to outside if (from != INTERNAL_INPUT_SOURCE) { bentoBox.transfer(tokenIn, from, address(this), amountIn); } else amountIn = bentoBox.balanceOf(tokenIn, address(this)); bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn); } } /// @notice UniswapV2 pool swap /// @param stream [pool, direction, recipient, fee] /// @param from Where to take liquidity for swap /// @param tokenIn Input token /// @param amountIn Amount of tokenIn to take for swap function swapUniV2( uint256 stream, address from, address tokenIn, uint256 amountIn ) private { address pool = stream.readAddress(); uint8 direction = stream.readUint8(); address to = stream.readAddress(); uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000 if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn); else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn); (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves(); require(r0 > 0 && r1 > 0, "Wrong pool reserves"); (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0); amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred uint256 amountInWithFee = amountIn * (1_000_000 - fee); uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee); (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0)); IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0)); } /// @notice Trident pool swap /// @param stream [pool, swapData] /// @param from Where to take liquidity for swap /// @param tokenIn Input token /// @param amountIn Amount of tokenIn to take for swap function swapTrident( uint256 stream, address from, address tokenIn, uint256 amountIn ) private { address pool = stream.readAddress(); bytes memory swapData = stream.readBytes(); if (from != INTERNAL_INPUT_SOURCE) { bentoBox.transfer(tokenIn, from, pool, amountIn); } IPool(pool).swap(swapData); } /// @notice UniswapV3 pool swap /// @param stream [pool, direction, recipient] /// @param from Where to take liquidity for swap /// @param tokenIn Input token /// @param amountIn Amount of tokenIn to take for swap function swapUniV3( uint256 stream, address from, address tokenIn, uint256 amountIn ) private { address pool = stream.readAddress(); bool zeroForOne = stream.readUint8() > 0; address recipient = stream.readAddress(); if (from == msg.sender) IERC20(tokenIn).safeTransferFrom( msg.sender, address(this), uint256(amountIn) ); lastCalledPool = pool; IUniswapV3Pool(pool).swap( recipient, zeroForOne, int256(amountIn), zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1, abi.encode(tokenIn) ); require( lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, "RouteProcessor.swapUniV3: unexpected" ); // Just to be sure } /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) public { require( msg.sender == lastCalledPool, "RouteProcessor.uniswapV3SwapCallback: call from unknown source" ); int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta; require( amount > 0, "RouteProcessor.uniswapV3SwapCallback: not positive amount" ); lastCalledPool = IMPOSSIBLE_POOL_ADDRESS; address tokenIn = abi.decode(data, (address)); IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount)); } /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call function algebraSwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external { uniswapV3SwapCallback(amount0Delta, amount1Delta, data); } /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call function pancakeV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external { uniswapV3SwapCallback(amount0Delta, amount1Delta, data); } /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token] /// @param from Where to take liquidity for swap /// @param tokenIn Input token /// @param amountIn Amount of tokenIn to take for swap function swapCurve( uint256 stream, address from, address tokenIn, uint256 amountIn ) private { address pool = stream.readAddress(); uint8 poolType = stream.readUint8(); int128 fromIndex = int8(stream.readUint8()); int128 toIndex = int8(stream.readUint8()); address to = stream.readAddress(); address tokenOut = stream.readAddress(); uint256 amountOut; if (tokenIn == NATIVE_ADDRESS) { amountOut = ICurve(pool).exchange{ value: amountIn }( fromIndex, toIndex, amountIn, 0 ); } else { if (from == msg.sender) IERC20(tokenIn).safeTransferFrom( msg.sender, address(this), amountIn ); IERC20(tokenIn).approveSafe(pool, amountIn); if (poolType == 0) amountOut = ICurve(pool).exchange( fromIndex, toIndex, amountIn, 0 ); else { uint256 balanceBefore = IERC20(tokenOut).balanceOf( address(this) ); ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0); uint256 balanceAfter = IERC20(tokenOut).balanceOf( address(this) ); amountOut = balanceAfter - balanceBefore; } } if (to != address(this)) { if (tokenOut == NATIVE_ADDRESS) { (bool success, ) = payable(to).call{ value: amountOut }(""); require( success, "RouteProcessor.swapCurve: Native token transfer failed" ); } else { IERC20(tokenOut).safeTransfer(to, amountOut); } } } } /// @notice Minimal BentoBox vault interface. /// @dev `token` is aliased as `address` from `IERC20` for simplicity. interface IBentoBoxMinimal { /// @notice Balance per ERC-20 token per account in shares. function balanceOf(address, address) external view returns (uint256); /// @dev Helper function to represent an `amount` of `token` in shares. /// @param token The ERC-20 token. /// @param amount The `token` amount. /// @param roundUp If the result `share` should be rounded up. /// @return share The token amount represented in shares. function toShare( address token, uint256 amount, bool roundUp ) external view returns (uint256 share); /// @dev Helper function to represent shares back into the `token` amount. /// @param token The ERC-20 token. /// @param share The amount of shares. /// @param roundUp If the result should be rounded up. /// @return amount The share amount back into native representation. function toAmount( address token, uint256 share, bool roundUp ) external view returns (uint256 amount); /// @notice Registers this contract so that users can approve it for BentoBox. function registerProtocol() external; /// @notice Deposit an amount of `token` represented in either `amount` or `share`. /// @param token The ERC-20 token to deposit. /// @param from which account to pull the tokens. /// @param to which account to push the tokens. /// @param amount Token amount in native representation to deposit. /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`. /// @return amountOut The amount deposited. /// @return shareOut The deposited amount represented in shares. function deposit( address token, address from, address to, uint256 amount, uint256 share ) external payable returns (uint256 amountOut, uint256 shareOut); /// @notice Withdraws an amount of `token` from a user account. /// @param token_ The ERC-20 token to withdraw. /// @param from which user to pull the tokens. /// @param to which user to push the tokens. /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied. /// @param share Like above, but `share` takes precedence over `amount`. function withdraw( address token_, address from, address to, uint256 amount, uint256 share ) external returns (uint256 amountOut, uint256 shareOut); /// @notice Transfer shares from a user account to another one. /// @param token The ERC-20 token to transfer. /// @param from which user to pull the tokens. /// @param to which user to push the tokens. /// @param share The amount of `token` in shares. function transfer( address token, address from, address to, uint256 share ) external; /// @dev Reads the Rebase `totals`from storage for a given token function totals(address token) external view returns (Rebase memory total); function strategyData( address token ) external view returns (StrategyData memory total); /// @dev Approves users' BentoBox assets to a "master" contract. function setMasterContractApproval( address user, address masterContract, bool approved, uint8 v, bytes32 r, bytes32 s ) external; function harvest( address token, bool balance, uint256 maxChangeAmount ) external; } interface ICurve { function exchange( int128 i, int128 j, uint256 dx, uint256 min_dy ) external payable returns (uint256); } interface ICurveLegacy { function exchange( int128 i, int128 j, uint256 dx, uint256 min_dy ) external payable; } /// @notice Trident pool interface. interface IPool { /// @notice Executes a swap from one token to another. /// @dev The input tokens must've already been sent to the pool. /// @param data ABI-encoded params that the pool requires. /// @return finalAmountOut The amount of output tokens that were sent to the user. function swap( bytes calldata data ) external returns (uint256 finalAmountOut); /// @notice Executes a swap from one token to another with a callback. /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback. /// @param data ABI-encoded params that the pool requires. /// @return finalAmountOut The amount of output tokens that were sent to the user. function flashSwap( bytes calldata data ) external returns (uint256 finalAmountOut); /// @notice Mints liquidity tokens. /// @param data ABI-encoded params that the pool requires. /// @return liquidity The amount of liquidity tokens that were minted for the user. function mint(bytes calldata data) external returns (uint256 liquidity); /// @notice Burns liquidity tokens. /// @dev The input LP tokens must've already been sent to the pool. /// @param data ABI-encoded params that the pool requires. /// @return withdrawnAmounts The amount of various output tokens that were sent to the user. function burn( bytes calldata data ) external returns (TokenAmount[] memory withdrawnAmounts); /// @notice Burns liquidity tokens for a single output token. /// @dev The input LP tokens must've already been sent to the pool. /// @param data ABI-encoded params that the pool requires. /// @return amountOut The amount of output tokens that were sent to the user. function burnSingle( bytes calldata data ) external returns (uint256 amountOut); /// @return A unique identifier for the pool type. function poolIdentifier() external pure returns (bytes32); /// @return An array of tokens supported by the pool. function getAssets() external view returns (address[] memory); /// @notice Simulates a trade and returns the expected output. /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library. /// @param data ABI-encoded params that the pool requires. /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed. function getAmountOut( bytes calldata data ) external view returns (uint256 finalAmountOut); /// @notice Simulates a trade and returns the expected output. /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library. /// @param data ABI-encoded params that the pool requires. /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed. function getAmountIn( bytes calldata data ) external view returns (uint256 finalAmountIn); /// @dev This event must be emitted on all swaps. event Swap( address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut ); /// @dev This struct frames output tokens for burns. struct TokenAmount { address token; uint256 amount; } } interface ITridentCLPool { function token0() external returns (address); function token1() external returns (address); function swap( address recipient, bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96, bool unwrapBento, bytes calldata data ) external returns (int256 amount0, int256 amount1); } interface IUniswapV2Pair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance( address owner, address spender ) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom( address from, address to, uint value ) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit( address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s ) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn( address indexed sender, uint amount0, uint amount1, address indexed to ); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns ( uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast ); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap( uint amount0Out, uint amount1Out, address to, bytes calldata data ) external; function skim(address to) external; function sync() external; function initialize(address, address) external; } interface IUniswapV3Pool { function token0() external returns (address); function token1() external returns (address); function swap( address recipient, bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96, bytes calldata data ) external returns (int256 amount0, int256 amount1); } interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; } /** @notice Simple read stream */ library InputStream { /** @notice Creates stream from data * @param data data */ function createStream( bytes memory data ) internal pure returns (uint256 stream) { assembly { stream := mload(0x40) mstore(0x40, add(stream, 64)) mstore(stream, data) let length := mload(data) mstore(add(stream, 32), add(data, length)) } } /** @notice Checks if stream is not empty * @param stream stream */ function isNotEmpty(uint256 stream) internal pure returns (bool) { uint256 pos; uint256 finish; assembly { pos := mload(stream) finish := mload(add(stream, 32)) } return pos < finish; } /** @notice Reads uint8 from the stream * @param stream stream */ function readUint8(uint256 stream) internal pure returns (uint8 res) { assembly { let pos := mload(stream) pos := add(pos, 1) res := mload(pos) mstore(stream, pos) } } /** @notice Reads uint16 from the stream * @param stream stream */ function readUint16(uint256 stream) internal pure returns (uint16 res) { assembly { let pos := mload(stream) pos := add(pos, 2) res := mload(pos) mstore(stream, pos) } } /** @notice Reads uint24 from the stream * @param stream stream */ function readUint24(uint256 stream) internal pure returns (uint24 res) { assembly { let pos := mload(stream) pos := add(pos, 3) res := mload(pos) mstore(stream, pos) } } /** @notice Reads uint32 from the stream * @param stream stream */ function readUint32(uint256 stream) internal pure returns (uint32 res) { assembly { let pos := mload(stream) pos := add(pos, 4) res := mload(pos) mstore(stream, pos) } } /** @notice Reads uint256 from the stream * @param stream stream */ function readUint(uint256 stream) internal pure returns (uint256 res) { assembly { let pos := mload(stream) pos := add(pos, 32) res := mload(pos) mstore(stream, pos) } } /** @notice Reads bytes32 from the stream * @param stream stream */ function readBytes32(uint256 stream) internal pure returns (bytes32 res) { assembly { let pos := mload(stream) pos := add(pos, 32) res := mload(pos) mstore(stream, pos) } } /** @notice Reads address from the stream * @param stream stream */ function readAddress(uint256 stream) internal pure returns (address res) { assembly { let pos := mload(stream) pos := add(pos, 20) res := mload(pos) mstore(stream, pos) } } /** @notice Reads bytes from the stream * @param stream stream */ function readBytes( uint256 stream ) internal pure returns (bytes memory res) { assembly { let pos := mload(stream) res := add(pos, 32) let length := mload(res) mstore(stream, add(res, length)) } } } library Approve { /** * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example) * @param token The token targeted by the call. * @param spender token spender * @param amount token amount */ function approveStable( IERC20 token, address spender, uint256 amount ) internal returns (bool) { (bool success, bytes memory data) = address(token).call( abi.encodeWithSelector(token.approve.selector, spender, amount) ); return success && (data.length == 0 || abi.decode(data, (bool))); } /** * @dev ERC20 approve that correct works with token.approve which reverts if amount and * current allowance are not zero simultaniously (USDT for example). * In second case it tries to set allowance to 0, and then back to amount. * @param token The token targeted by the call. * @param spender token spender * @param amount token amount */ function approveSafe( IERC20 token, address spender, uint256 amount ) internal returns (bool) { return approveStable(token, spender, amount) || (approveStable(token, spender, 0) && approveStable(token, spender, amount)); } } struct Rebase { uint128 elastic; uint128 base; } struct StrategyData { uint64 strategyStartDate; uint64 targetPercentage; uint128 balance; // the balance of the strategy that BentoBox thinks is in there } /// @notice A rebasing library library RebaseLibrary { /// @notice Calculates the base value in relationship to `elastic` and `total`. function toBase( Rebase memory total, uint256 elastic ) internal pure returns (uint256 base) { if (total.elastic == 0) { base = elastic; } else { base = (elastic * total.base) / total.elastic; } } /// @notice Calculates the elastic value in relationship to `base` and `total`. function toElastic( Rebase memory total, uint256 base ) internal pure returns (uint256 elastic) { if (total.base == 0) { elastic = base; } else { elastic = (base * total.elastic) / total.base; } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_bentoBox","type":"address"},{"internalType":"address[]","name":"priviledgedUserList","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"MinimalOutputBalanceViolation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"Route","type":"event"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"algebraSwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bentoBox","outputs":[{"internalType":"contract IBentoBoxMinimal","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"pancakeV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"priviledgedUsers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"route","type":"bytes"}],"name":"processRoute","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"priviledge","type":"bool"}],"name":"setPriviledge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"transferValueTo","type":"address"},{"internalType":"uint256","name":"amountValueTransfer","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"route","type":"bytes"}],"name":"transferValueAndprocessRoute","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040213803806200402183398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000295565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200028e57634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613d23620002fe60003960008181610151015281816115030152818161247a015281816124de015281816125480152818161260d015281816126ba0152818161279e015281816128a50152818161295101528181612a200152612b320152613d236000f3fe6080604052600436106100d65760003560e01c80638456cb591161007f5780639a1f3406116100595780639a1f340614610200578063cd0fb7a714610220578063f2fde38b14610260578063fa461e331461028057600080fd5b80638456cb59146101ad5780638da5cb5b146101c257806393b3774c146101ed57600080fd5b80632c8958f6116100b05780632c8958f6146100f95780636b2ace871461013f578063715018a61461019857600080fd5b8063046f7da2146100e257806323a69e75146100f95780632646478b1461011957600080fd5b366100dd57005b600080fd5b3480156100ee57600080fd5b506100f76102a0565b005b34801561010557600080fd5b506100f7610114366004613592565b6103a8565b61012c61012736600461370e565b6103ba565b6040519081526020015b60405180910390f35b34801561014b57600080fd5b506101737f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610136565b3480156101a457600080fd5b506100f7610564565b3480156101b957600080fd5b506100f7610578565b3480156101ce57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610173565b61012c6101fb366004613795565b61067b565b34801561020c57600080fd5b506100f761021b366004613848565b61089a565b34801561022c57600080fd5b5061025061023b366004613881565b60016020526000908152604090205460ff1681565b6040519015158152602001610136565b34801561026c57600080fd5b506100f761027b366004613881565b6108f8565b34801561028c57600080fd5b506100f761029b366004613592565b6109af565b60005473ffffffffffffffffffffffffffffffffffffffff163314806102d557503360009081526001602052604090205460ff165b610366576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103b4848484846109af565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b65640000000000000000604482015260640161035d565b6002547501000000000000000000000000000000000000000000900460ff166001146104cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973207061757365640000000000000000604482015260640161035d565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610519878787878787610b5d565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b61056c6111a0565b6105766000611221565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314806105ad57503360009081526001602052604090205460ff165b610639576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c65676564207573657200000000000000000000000000000000606482015260840161035d565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610705576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b65640000000000000000604482015260640161035d565b6002547501000000000000000000000000000000000000000000900460ff1660011461078d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973207061757365640000000000000000604482015260640161035d565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055604051600090819073ffffffffffffffffffffffffffffffffffffffff8c16908b908381818185875af1925050503d8060008114610826576040519150601f19603f3d011682016040523d82523d6000602084013e61082b565b606091505b50915091508161083d57805181602001fd5b61084b898989898989610b5d565b92505050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b6108a26111a0565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6109006111a0565b73ffffffffffffffffffffffffffffffffffffffff81166109a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161035d565b6109ac81611221565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610a56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f757263650000606482015260840161035d565b6000808513610a655783610a67565b845b905060008113610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e7400000000000000606482015260840161035d565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610b3283850185613881565b9050610b5573ffffffffffffffffffffffffffffffffffffffff82163384611296565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff881673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610c24576040517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8916906370a0823190602401602060405180830381865afa158015610bfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1f91906138a5565b610c27565b60005b9050600073ffffffffffffffffffffffffffffffffffffffff871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610cf1576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301528816906370a0823190602401602060405180830381865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec91906138a5565b610d0a565b8473ffffffffffffffffffffffffffffffffffffffff16315b905087600080610d2e87604080518082019091528181528151909101602082015290565b90505b805160208201511115610e81576000610d508280516001018051915290565b90508060ff16600103610d7c576000610d688361136f565b905083600003610d76578094505b50610e70565b8060ff16600203610d9657610d91828d611434565b610e70565b8060ff16600303610dac576000610d6883611454565b8060ff16600403610dc057610d918261147a565b8060ff16600503610dd457610d91826114a0565b8060ff16600603610de957610d918d836115a5565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f646500000000000000000000000000000000000000000000000000000000606482015260840161035d565b610e79836138ed565b925050610d31565b506000905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610f4a576040517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa158015610f21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4591906138a5565b610f4d565b60005b905083610f5a8b83613925565b1015610fe8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e0000000000000000000000000000000000606482015260840161035d565b600073ffffffffffffffffffffffffffffffffffffffff8a1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146110b0576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff89811660048301528b16906370a0823190602401602060405180830381865afa158015611087573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ab91906138a5565b6110c9565b8773ffffffffffffffffffffffffffffffffffffffff16315b90506110d58985613925565b81101561111b576110e6848261393e565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161035d91815260200190565b611125848261393e565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610576576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161035d565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261136a9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611638565b505050565b6000806113828380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa1580156113ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141391906138a5565b91508115611422576001820391505b61142e83308385611747565b50919050565b60006114468380516014018051915290565b905061136a83338385611747565b47611475823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611747565b919050565b600061148c8280516014018051915290565b905061149c8260008360006117a2565b5050565b60006114b28280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa15801561154a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156e91906138a5565b90508015611599577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61136a83308484611747565b60006115b78280516020018051915290565b905060006115cb8380516020018051915290565b905060006115df8480516001018051915290565b905060006115f38580516020018051915290565b905060006116078680516020018051915290565b905061162f73ffffffffffffffffffffffffffffffffffffffff8816333088888888886118d4565b50505050505050565b600061169a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611b549092919063ffffffff16565b90508051600014806116bb5750808060200190518101906116bb9190613951565b61136a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161035d565b60006117598580516001018051915290565b905060005b8160ff16811015610b5557600061177b8780516002018051915290565b61ffff8082168602049485900394909150611798888888846117a2565b505060010161175e565b60006117b48580516001018051915290565b90508060ff166000036117d2576117cd85858585611b6b565b6118cd565b8060ff166001036117e9576117cd85858585611f1e565b8060ff16600203611800576117cd8585858561215d565b8060ff16600303611817576117cd85858585612410565b8060ff1660040361182e576117cd85858585612a96565b8060ff16600503611845576117cd85858585612c24565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f6500000000000000000000000000000000000000000000000000000000000000606482015260840161035d565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611944573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196891906138a5565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611a0257600080fd5b505af1158015611a16573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aad91906138a5565b9050611aba826001613925565b8114611b48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015260840161035d565b50505050505050505050565b6060611b6384846000856131f7565b949350505050565b6000611b7d8580516014018051915290565b90506000611b918680516001018051915290565b90506000611ba58780516014018051915290565b90506000611bb98880516003018051915290565b90503073ffffffffffffffffffffffffffffffffffffffff881603611bfe57611bf973ffffffffffffffffffffffffffffffffffffffff87168587611296565b611c3d565b3373ffffffffffffffffffffffffffffffffffffffff881603611c3d57611c3d73ffffffffffffffffffffffffffffffffffffffff8716338688613310565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611c8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611caf919061398c565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150600082118015611ce45750600081115b611d4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c20726573657276657300000000000000000000000000604482015260640161035d565b6000808660ff16600114611d5f578284611d62565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015611dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfa91906138a5565b611e04919061393e565b98506000611e1586620f42406139dc565b611e249062ffffff168b6139ff565b9050600081611e3685620f42406139ff565b611e409190613925565b611e4a84846139ff565b611e549190613a16565b90506000808a60ff16600114611e6c57826000611e70565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f90611eda90859085908f9060248101613abf565b600060405180830381600087803b158015611ef457600080fd5b505af1158015611f08573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b6000611f308580516014018051915290565b9050600080611f458780516001018051915290565b60ff161190506000611f5d8780516014018051915290565b90503373ffffffffffffffffffffffffffffffffffffffff871603611f9e57611f9e73ffffffffffffffffffffffffffffffffffffffff8616333087613310565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816120125761200d600173fffd8963efd1fc6a506488495d951d5263988d26613afa565b612022565b6120226401000276a36001613b27565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612072959493929190613b54565b60408051808303816000875af1158015612090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b49190613b9b565b505060025473ffffffffffffffffffffffffffffffffffffffff1660011461162f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f6374656400000000000000000000000000000000000000000000000000000000606482015260840161035d565b600061216f8580516001018051915290565b905060006121838680516014018051915290565b9050600180831690036122555760006121a28780516014018051915290565b905060028316600003612211578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b1580156121f757600080fd5b505af115801561220b573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff8216301461224f5761224f73ffffffffffffffffffffffffffffffffffffffff82168386611296565b50610b55565b60028216600003612320573373ffffffffffffffffffffffffffffffffffffffff86160361229f5761229f73ffffffffffffffffffffffffffffffffffffffff8516333086613310565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561230757600080fd5b505af115801561231b573d6000803e3d6000fd5b505050505b60008173ffffffffffffffffffffffffffffffffffffffff168460405160006040518083038185875af1925050503d806000811461237a576040519150601f19603f3d011682016040523d82523d6000602084013e61237f565b606091505b505090508061162f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f526f75746550726f636573736f722e777261704e61746976653a204e6174697660448201527f6520746f6b656e207472616e73666572206661696c6564000000000000000000606482015260840161035d565b60006124228580516001018051915290565b905060006124368680516014018051915290565b905060ff82161561282f573073ffffffffffffffffffffffffffffffffffffffff8616036124a45761249f73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611296565b612759565b3373ffffffffffffffffffffffffffffffffffffffff8616036125035761249f73ffffffffffffffffffffffffffffffffffffffff8516337f000000000000000000000000000000000000000000000000000000000000000086613310565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561258e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b29190613bdf565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126789190613c52565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa15801561271e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274291906138a5565b61274c9190613925565b612756919061393e565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128289190613b9b565b5050610b55565b73ffffffffffffffffffffffffffffffffffffffff851615612906576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b1580156128e957600080fd5b505af11580156128fd573d6000803e3d6000fd5b505050506129bf565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612998573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bc91906138a5565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c9190613b9b565b5050505050505050565b6000612aa88580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612b8f576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612b7657600080fd5b505af1158015612b8a573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612be1908490600401613cbe565b6020604051808303816000875af1158015612c00573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162f91906138a5565b6000612c368580516014018051915290565b90506000612c4a8680516001018051915290565b90506000612c5e8780516001018051915290565b60000b90506000612c758880516001018051915290565b60000b90506000612c8c8980516014018051915290565b90506000612ca08a80516014018051915290565b905060007fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8a1601612d94576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af1158015612d68573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d8d91906138a5565b9050613079565b3373ffffffffffffffffffffffffffffffffffffffff8b1603612dd357612dd373ffffffffffffffffffffffffffffffffffffffff8a1633308b613310565b612df473ffffffffffffffffffffffffffffffffffffffff8a16888a61336e565b508560ff16600003612eaa576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015612e86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d8d91906138a5565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015612f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f3b91906138a5565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b158015612fbf57600080fd5b505af1158015612fd3573d6000803e3d6000fd5b50506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000925073ffffffffffffffffffffffffffffffffffffffff861691506370a0823190602401602060405180830381865afa158015613044573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061306891906138a5565b9050613074828261393e565b925050505b73ffffffffffffffffffffffffffffffffffffffff831630146131ea577fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8316016131c95760008373ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461312d576040519150601f19603f3d011682016040523d82523d6000602084013e613132565b606091505b50509050806131c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f526f75746550726f636573736f722e7377617043757276653a204e617469766560448201527f20746f6b656e207472616e73666572206661696c656400000000000000000000606482015260840161035d565b506131ea565b6131ea73ffffffffffffffffffffffffffffffffffffffff83168483611296565b5050505050505050505050565b606082471015613289576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161035d565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516132b29190613cd1565b60006040518083038185875af1925050503d80600081146132ef576040519150601f19603f3d011682016040523d82523d6000602084013e6132f4565b606091505b50915091506133058783838761339f565b979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103b49085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016112e8565b600061337b84848461343f565b80611b63575061338d8484600061343f565b8015611b635750611b6384848461343f565b6060831561343557825160000361342e5773ffffffffffffffffffffffffffffffffffffffff85163b61342e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161035d565b5081611b63565b611b63838361354e565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052915160009283928392918816916134d89190613cd1565b6000604051808303816000865af19150503d8060008114613515576040519150601f19603f3d011682016040523d82523d6000602084013e61351a565b606091505b50915091508180156135445750805115806135445750808060200190518101906135449190613951565b9695505050505050565b81511561355e5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035d9190613cbe565b600080600080606085870312156135a857600080fd5b8435935060208501359250604085013567ffffffffffffffff808211156135ce57600080fd5b818701915087601f8301126135e257600080fd5b8135818111156135f157600080fd5b88602082850101111561360357600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109ac57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261367457600080fd5b813567ffffffffffffffff8082111561368f5761368f613634565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156136d5576136d5613634565b816040528381528660208588010111156136ee57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561372757600080fd5b863561373281613612565b955060208701359450604087013561374981613612565b935060608701359250608087013561376081613612565b915060a087013567ffffffffffffffff81111561377c57600080fd5b61378889828a01613663565b9150509295509295509295565b600080600080600080600080610100898b0312156137b257600080fd5b88356137bd81613612565b97506020890135965060408901356137d481613612565b95506060890135945060808901356137eb81613612565b935060a0890135925060c089013561380281613612565b915060e089013567ffffffffffffffff81111561381e57600080fd5b61382a8b828c01613663565b9150509295985092959890939650565b80151581146109ac57600080fd5b6000806040838503121561385b57600080fd5b823561386681613612565b915060208301356138768161383a565b809150509250929050565b60006020828403121561389357600080fd5b813561389e81613612565b9392505050565b6000602082840312156138b757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361391e5761391e6138be565b5060010190565b80820180821115613938576139386138be565b92915050565b81810381811115613938576139386138be565b60006020828403121561396357600080fd5b815161389e8161383a565b80516dffffffffffffffffffffffffffff8116811461147557600080fd5b6000806000606084860312156139a157600080fd5b6139aa8461396e565b92506139b86020850161396e565b9150604084015163ffffffff811681146139d157600080fd5b809150509250925092565b62ffffff8281168282160390808211156139f8576139f86138be565b5092915050565b8082028115828204841417613938576139386138be565b600082613a4c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613a6c578181015183820152602001613a54565b50506000910152565b60008151808452613a8d816020860160208601613a51565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135446080830184613a75565b73ffffffffffffffffffffffffffffffffffffffff8281168282160390808211156139f8576139f86138be565b73ffffffffffffffffffffffffffffffffffffffff8181168382160190808211156139f8576139f86138be565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a0608083015261330560a0830184613a75565b60008060408385031215613bae57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461147557600080fd5b600060408284031215613bf157600080fd5b6040516040810181811067ffffffffffffffff82111715613c1457613c14613634565b604052613c2083613bbf565b8152613c2e60208401613bbf565b60208201529392505050565b805167ffffffffffffffff8116811461147557600080fd5b600060608284031215613c6457600080fd5b6040516060810181811067ffffffffffffffff82111715613c8757613c87613634565b604052613c9383613c3a565b8152613ca160208401613c3a565b6020820152613cb260408401613bbf565b60408201529392505050565b60208152600061389e6020830184613a75565b60008251613ce3818460208701613a51565b919091019291505056fea264697066735822122066b57539997c8cb99ab953370484ebb43508a94ef324cf6e699d651e5147efa364736f6c6343000811003300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000029dacdf7ccadf4ee67c923b4c22255a4b2494ed7
Deployed Bytecode
0x6080604052600436106100d65760003560e01c80638456cb591161007f5780639a1f3406116100595780639a1f340614610200578063cd0fb7a714610220578063f2fde38b14610260578063fa461e331461028057600080fd5b80638456cb59146101ad5780638da5cb5b146101c257806393b3774c146101ed57600080fd5b80632c8958f6116100b05780632c8958f6146100f95780636b2ace871461013f578063715018a61461019857600080fd5b8063046f7da2146100e257806323a69e75146100f95780632646478b1461011957600080fd5b366100dd57005b600080fd5b3480156100ee57600080fd5b506100f76102a0565b005b34801561010557600080fd5b506100f7610114366004613592565b6103a8565b61012c61012736600461370e565b6103ba565b6040519081526020015b60405180910390f35b34801561014b57600080fd5b506101737f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610136565b3480156101a457600080fd5b506100f7610564565b3480156101b957600080fd5b506100f7610578565b3480156101ce57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610173565b61012c6101fb366004613795565b61067b565b34801561020c57600080fd5b506100f761021b366004613848565b61089a565b34801561022c57600080fd5b5061025061023b366004613881565b60016020526000908152604090205460ff1681565b6040519015158152602001610136565b34801561026c57600080fd5b506100f761027b366004613881565b6108f8565b34801561028c57600080fd5b506100f761029b366004613592565b6109af565b60005473ffffffffffffffffffffffffffffffffffffffff163314806102d557503360009081526001602052604090205460ff165b610366576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103b4848484846109af565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b65640000000000000000604482015260640161035d565b6002547501000000000000000000000000000000000000000000900460ff166001146104cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973207061757365640000000000000000604482015260640161035d565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610519878787878787610b5d565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b61056c6111a0565b6105766000611221565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314806105ad57503360009081526001602052604090205460ff165b610639576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c65676564207573657200000000000000000000000000000000606482015260840161035d565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610705576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b65640000000000000000604482015260640161035d565b6002547501000000000000000000000000000000000000000000900460ff1660011461078d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973207061757365640000000000000000604482015260640161035d565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055604051600090819073ffffffffffffffffffffffffffffffffffffffff8c16908b908381818185875af1925050503d8060008114610826576040519150601f19603f3d011682016040523d82523d6000602084013e61082b565b606091505b50915091508161083d57805181602001fd5b61084b898989898989610b5d565b92505050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b6108a26111a0565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6109006111a0565b73ffffffffffffffffffffffffffffffffffffffff81166109a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161035d565b6109ac81611221565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610a56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f757263650000606482015260840161035d565b6000808513610a655783610a67565b845b905060008113610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e7400000000000000606482015260840161035d565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610b3283850185613881565b9050610b5573ffffffffffffffffffffffffffffffffffffffff82163384611296565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff881673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610c24576040517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8916906370a0823190602401602060405180830381865afa158015610bfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1f91906138a5565b610c27565b60005b9050600073ffffffffffffffffffffffffffffffffffffffff871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610cf1576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301528816906370a0823190602401602060405180830381865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec91906138a5565b610d0a565b8473ffffffffffffffffffffffffffffffffffffffff16315b905087600080610d2e87604080518082019091528181528151909101602082015290565b90505b805160208201511115610e81576000610d508280516001018051915290565b90508060ff16600103610d7c576000610d688361136f565b905083600003610d76578094505b50610e70565b8060ff16600203610d9657610d91828d611434565b610e70565b8060ff16600303610dac576000610d6883611454565b8060ff16600403610dc057610d918261147a565b8060ff16600503610dd457610d91826114a0565b8060ff16600603610de957610d918d836115a5565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f646500000000000000000000000000000000000000000000000000000000606482015260840161035d565b610e79836138ed565b925050610d31565b506000905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610f4a576040517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa158015610f21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4591906138a5565b610f4d565b60005b905083610f5a8b83613925565b1015610fe8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e0000000000000000000000000000000000606482015260840161035d565b600073ffffffffffffffffffffffffffffffffffffffff8a1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146110b0576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff89811660048301528b16906370a0823190602401602060405180830381865afa158015611087573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ab91906138a5565b6110c9565b8773ffffffffffffffffffffffffffffffffffffffff16315b90506110d58985613925565b81101561111b576110e6848261393e565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161035d91815260200190565b611125848261393e565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610576576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161035d565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261136a9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611638565b505050565b6000806113828380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa1580156113ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141391906138a5565b91508115611422576001820391505b61142e83308385611747565b50919050565b60006114468380516014018051915290565b905061136a83338385611747565b47611475823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611747565b919050565b600061148c8280516014018051915290565b905061149c8260008360006117a2565b5050565b60006114b28280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa15801561154a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156e91906138a5565b90508015611599577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61136a83308484611747565b60006115b78280516020018051915290565b905060006115cb8380516020018051915290565b905060006115df8480516001018051915290565b905060006115f38580516020018051915290565b905060006116078680516020018051915290565b905061162f73ffffffffffffffffffffffffffffffffffffffff8816333088888888886118d4565b50505050505050565b600061169a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611b549092919063ffffffff16565b90508051600014806116bb5750808060200190518101906116bb9190613951565b61136a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161035d565b60006117598580516001018051915290565b905060005b8160ff16811015610b5557600061177b8780516002018051915290565b61ffff8082168602049485900394909150611798888888846117a2565b505060010161175e565b60006117b48580516001018051915290565b90508060ff166000036117d2576117cd85858585611b6b565b6118cd565b8060ff166001036117e9576117cd85858585611f1e565b8060ff16600203611800576117cd8585858561215d565b8060ff16600303611817576117cd85858585612410565b8060ff1660040361182e576117cd85858585612a96565b8060ff16600503611845576117cd85858585612c24565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f6500000000000000000000000000000000000000000000000000000000000000606482015260840161035d565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611944573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196891906138a5565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611a0257600080fd5b505af1158015611a16573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aad91906138a5565b9050611aba826001613925565b8114611b48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015260840161035d565b50505050505050505050565b6060611b6384846000856131f7565b949350505050565b6000611b7d8580516014018051915290565b90506000611b918680516001018051915290565b90506000611ba58780516014018051915290565b90506000611bb98880516003018051915290565b90503073ffffffffffffffffffffffffffffffffffffffff881603611bfe57611bf973ffffffffffffffffffffffffffffffffffffffff87168587611296565b611c3d565b3373ffffffffffffffffffffffffffffffffffffffff881603611c3d57611c3d73ffffffffffffffffffffffffffffffffffffffff8716338688613310565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611c8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611caf919061398c565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150600082118015611ce45750600081115b611d4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c20726573657276657300000000000000000000000000604482015260640161035d565b6000808660ff16600114611d5f578284611d62565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015611dd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfa91906138a5565b611e04919061393e565b98506000611e1586620f42406139dc565b611e249062ffffff168b6139ff565b9050600081611e3685620f42406139ff565b611e409190613925565b611e4a84846139ff565b611e549190613a16565b90506000808a60ff16600114611e6c57826000611e70565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f90611eda90859085908f9060248101613abf565b600060405180830381600087803b158015611ef457600080fd5b505af1158015611f08573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b6000611f308580516014018051915290565b9050600080611f458780516001018051915290565b60ff161190506000611f5d8780516014018051915290565b90503373ffffffffffffffffffffffffffffffffffffffff871603611f9e57611f9e73ffffffffffffffffffffffffffffffffffffffff8616333087613310565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816120125761200d600173fffd8963efd1fc6a506488495d951d5263988d26613afa565b612022565b6120226401000276a36001613b27565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612072959493929190613b54565b60408051808303816000875af1158015612090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b49190613b9b565b505060025473ffffffffffffffffffffffffffffffffffffffff1660011461162f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f6374656400000000000000000000000000000000000000000000000000000000606482015260840161035d565b600061216f8580516001018051915290565b905060006121838680516014018051915290565b9050600180831690036122555760006121a28780516014018051915290565b905060028316600003612211578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b1580156121f757600080fd5b505af115801561220b573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff8216301461224f5761224f73ffffffffffffffffffffffffffffffffffffffff82168386611296565b50610b55565b60028216600003612320573373ffffffffffffffffffffffffffffffffffffffff86160361229f5761229f73ffffffffffffffffffffffffffffffffffffffff8516333086613310565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561230757600080fd5b505af115801561231b573d6000803e3d6000fd5b505050505b60008173ffffffffffffffffffffffffffffffffffffffff168460405160006040518083038185875af1925050503d806000811461237a576040519150601f19603f3d011682016040523d82523d6000602084013e61237f565b606091505b505090508061162f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f526f75746550726f636573736f722e777261704e61746976653a204e6174697660448201527f6520746f6b656e207472616e73666572206661696c6564000000000000000000606482015260840161035d565b60006124228580516001018051915290565b905060006124368680516014018051915290565b905060ff82161561282f573073ffffffffffffffffffffffffffffffffffffffff8616036124a45761249f73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611296565b612759565b3373ffffffffffffffffffffffffffffffffffffffff8616036125035761249f73ffffffffffffffffffffffffffffffffffffffff8516337f000000000000000000000000000000000000000000000000000000000000000086613310565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561258e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b29190613bdf565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126789190613c52565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa15801561271e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274291906138a5565b61274c9190613925565b612756919061393e565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128289190613b9b565b5050610b55565b73ffffffffffffffffffffffffffffffffffffffff851615612906576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b1580156128e957600080fd5b505af11580156128fd573d6000803e3d6000fd5b505050506129bf565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612998573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129bc91906138a5565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c9190613b9b565b5050505050505050565b6000612aa88580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612b8f576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612b7657600080fd5b505af1158015612b8a573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612be1908490600401613cbe565b6020604051808303816000875af1158015612c00573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162f91906138a5565b6000612c368580516014018051915290565b90506000612c4a8680516001018051915290565b90506000612c5e8780516001018051915290565b60000b90506000612c758880516001018051915290565b60000b90506000612c8c8980516014018051915290565b90506000612ca08a80516014018051915290565b905060007fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8a1601612d94576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af1158015612d68573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d8d91906138a5565b9050613079565b3373ffffffffffffffffffffffffffffffffffffffff8b1603612dd357612dd373ffffffffffffffffffffffffffffffffffffffff8a1633308b613310565b612df473ffffffffffffffffffffffffffffffffffffffff8a16888a61336e565b508560ff16600003612eaa576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015612e86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d8d91906138a5565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015612f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f3b91906138a5565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b158015612fbf57600080fd5b505af1158015612fd3573d6000803e3d6000fd5b50506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000925073ffffffffffffffffffffffffffffffffffffffff861691506370a0823190602401602060405180830381865afa158015613044573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061306891906138a5565b9050613074828261393e565b925050505b73ffffffffffffffffffffffffffffffffffffffff831630146131ea577fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8316016131c95760008373ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461312d576040519150601f19603f3d011682016040523d82523d6000602084013e613132565b606091505b50509050806131c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f526f75746550726f636573736f722e7377617043757276653a204e617469766560448201527f20746f6b656e207472616e73666572206661696c656400000000000000000000606482015260840161035d565b506131ea565b6131ea73ffffffffffffffffffffffffffffffffffffffff83168483611296565b5050505050505050505050565b606082471015613289576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161035d565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516132b29190613cd1565b60006040518083038185875af1925050503d80600081146132ef576040519150601f19603f3d011682016040523d82523d6000602084013e6132f4565b606091505b50915091506133058783838761339f565b979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103b49085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016112e8565b600061337b84848461343f565b80611b63575061338d8484600061343f565b8015611b635750611b6384848461343f565b6060831561343557825160000361342e5773ffffffffffffffffffffffffffffffffffffffff85163b61342e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161035d565b5081611b63565b611b63838361354e565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052915160009283928392918816916134d89190613cd1565b6000604051808303816000865af19150503d8060008114613515576040519150601f19603f3d011682016040523d82523d6000602084013e61351a565b606091505b50915091508180156135445750805115806135445750808060200190518101906135449190613951565b9695505050505050565b81511561355e5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035d9190613cbe565b600080600080606085870312156135a857600080fd5b8435935060208501359250604085013567ffffffffffffffff808211156135ce57600080fd5b818701915087601f8301126135e257600080fd5b8135818111156135f157600080fd5b88602082850101111561360357600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109ac57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261367457600080fd5b813567ffffffffffffffff8082111561368f5761368f613634565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156136d5576136d5613634565b816040528381528660208588010111156136ee57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561372757600080fd5b863561373281613612565b955060208701359450604087013561374981613612565b935060608701359250608087013561376081613612565b915060a087013567ffffffffffffffff81111561377c57600080fd5b61378889828a01613663565b9150509295509295509295565b600080600080600080600080610100898b0312156137b257600080fd5b88356137bd81613612565b97506020890135965060408901356137d481613612565b95506060890135945060808901356137eb81613612565b935060a0890135925060c089013561380281613612565b915060e089013567ffffffffffffffff81111561381e57600080fd5b61382a8b828c01613663565b9150509295985092959890939650565b80151581146109ac57600080fd5b6000806040838503121561385b57600080fd5b823561386681613612565b915060208301356138768161383a565b809150509250929050565b60006020828403121561389357600080fd5b813561389e81613612565b9392505050565b6000602082840312156138b757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361391e5761391e6138be565b5060010190565b80820180821115613938576139386138be565b92915050565b81810381811115613938576139386138be565b60006020828403121561396357600080fd5b815161389e8161383a565b80516dffffffffffffffffffffffffffff8116811461147557600080fd5b6000806000606084860312156139a157600080fd5b6139aa8461396e565b92506139b86020850161396e565b9150604084015163ffffffff811681146139d157600080fd5b809150509250925092565b62ffffff8281168282160390808211156139f8576139f86138be565b5092915050565b8082028115828204841417613938576139386138be565b600082613a4c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613a6c578181015183820152602001613a54565b50506000910152565b60008151808452613a8d816020860160208601613a51565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135446080830184613a75565b73ffffffffffffffffffffffffffffffffffffffff8281168282160390808211156139f8576139f86138be565b73ffffffffffffffffffffffffffffffffffffffff8181168382160190808211156139f8576139f86138be565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a0608083015261330560a0830184613a75565b60008060408385031215613bae57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461147557600080fd5b600060408284031215613bf157600080fd5b6040516040810181811067ffffffffffffffff82111715613c1457613c14613634565b604052613c2083613bbf565b8152613c2e60208401613bbf565b60208201529392505050565b805167ffffffffffffffff8116811461147557600080fd5b600060608284031215613c6457600080fd5b6040516060810181811067ffffffffffffffff82111715613c8757613c87613634565b604052613c9383613c3a565b8152613ca160208401613c3a565b6020820152613cb260408401613bbf565b60408201529392505050565b60208152600061389e6020830184613a75565b60008251613ce3818460208701613a51565b919091019291505056fea264697066735822122066b57539997c8cb99ab953370484ebb43508a94ef324cf6e699d651e5147efa364736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000029dacdf7ccadf4ee67c923b4c22255a4b2494ed7
-----Decoded View---------------
Arg [0] : _bentoBox (address): 0x0000000000000000000000000000000000000000
Arg [1] : priviledgedUserList (address[]): 0x29DaCdF7cCaDf4eE67c923b4C22255A4B2494eD7
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [3] : 00000000000000000000000029dacdf7ccadf4ee67c923b4c22255a4b2494ed7
Deployed Bytecode Sourcemap
26426:24189:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28162:92;;;;;;;;;;;;;:::i;:::-;;47991:211;;;;;;;;;;-1:-1:-1;47991:211:0;;;;;:::i;:::-;;:::i;28687:470::-;;;;;;:::i;:::-;;:::i;:::-;;;2901:25:1;;;2889:2;2874:18;28687:470:0;;;;;;;;26909:42;;;;;;;;;;;;;;;;;;3138::1;3126:55;;;3108:74;;3096:2;3081:18;26909:42:0;2937:251:1;17545:103:0;;;;;;;;;;;;;:::i;28067:87::-;;;;;;;;;;;;;:::i;16904:::-;;;;;;;;;;-1:-1:-1;16950:7:0;16977:6;;;16904:87;;29674:837;;;;;;:::i;:::-;;:::i;27932:127::-;;;;;;;;;;-1:-1:-1;27932:127:0;;;;;:::i;:::-;;:::i;26958:48::-;;;;;;;;;;-1:-1:-1;26958:48:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;5451:14:1;;5444:22;5426:41;;5414:2;5399:18;26958:48:0;5286:187:1;17803:201:0;;;;;;;;;;-1:-1:-1;17803:201:0;;;;;:::i;:::-;;:::i;45482:672::-;;;;;;;;;;-1:-1:-1;45482:672:0;;;;;:::i;:::-;;:::i;28162:92::-;16950:7;16977:6;;;27447:10;:21;;:53;;-1:-1:-1;27489:10:0;27472:28;;;;:16;:28;;;;;;;;27447:53;27425:151;;;;;;;5680:2:1;27425:151:0;;;5662:21:1;5719:2;5699:18;;;5692:30;5758:34;5738:18;;;5731:62;5829:18;5809;;;5802:46;5865:19;;27425:151:0;;;;;;;;;28227:6:::1;:19:::0;;;::::1;::::0;::::1;::::0;;28162:92::o;47991:211::-;48139:55;48161:12;48175;48189:4;;48139:21;:55::i;:::-;47991:211;;;;:::o;28687:470::-;27169:8;;28908:17;;27169:8;;;:22;:8;25681:1;27169:22;27161:59;;;;;;;6097:2:1;27161:59:0;;;6079:21:1;6136:2;6116:18;;;6109:30;6175:26;6155:18;;;6148:54;6219:18;;27161:59:0;5895:348:1;27161:59:0;27239:6;;;;;:20;:6;25741:1;27239:20;27231:57;;;;;;;6450:2:1;27231:57:0;;;6432:21:1;6489:2;6469:18;;;6462:30;6528:26;6508:18;;;6501:54;6572:18;;27231:57:0;6248:348:1;27231:57:0;25649:1;27299:17;;;;;;;;28958:191:::1;28997:7:::0;29023:8;29050;29077:12;29108:2;29129:5;28958:20:::1;:191::i;:::-;28938:211;;27339:8:::0;:21;;;;;;;;28687:470;;-1:-1:-1;;;;;;28687:470:0:o;17545:103::-;16790:13;:11;:13::i;:::-;17610:30:::1;17637:1;17610:18;:30::i;:::-;17545:103::o:0;28067:87::-;16950:7;16977:6;;;27447:10;:21;;:53;;-1:-1:-1;27489:10:0;27472:28;;;;:16;:28;;;;;;;;27447:53;27425:151;;;;;;;5680:2:1;27425:151:0;;;5662:21:1;5719:2;5699:18;;;5692:30;5758:34;5738:18;;;5731:62;5829:18;5809;;;5802:46;5865:19;;27425:151:0;5478:412:1;27425:151:0;25709:1:::1;28131:15:::0;;;::::1;::::0;::::1;::::0;;28067:87::o;29674:837::-;27169:8;;29991:17;;27169:8;;;:22;:8;25681:1;27169:22;27161:59;;;;;;;6097:2:1;27161:59:0;;;6079:21:1;6136:2;6116:18;;;6109:30;6175:26;6155:18;;;6148:54;6219:18;;27161:59:0;5895:348:1;27161:59:0;27239:6;;;;;:20;:6;25741:1;27239:20;27231:57;;;;;;;6450:2:1;27231:57:0;;;6432:21:1;6489:2;6469:18;;;6462:30;6528:26;6508:18;;;6501:54;6572:18;;27231:57:0;6248:348:1;27231:57:0;25649:1;27299:17;;;;;;;;30064:76:::1;::::0;-1:-1:-1;;;;30064:20:0::1;::::0;::::1;::::0;30106:19;;-1:-1:-1;30064:76:0;-1:-1:-1;30064:76:0;30106:19;30064:20;:76:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30021:119;;;;30156:7;30151:131;;30243:11;30237:18;30223:11;30219:2;30215:20;30208:48;30151:131;30312:191;30351:7;30377:8;30404;30431:12;30462:2;30483:5;30312:20;:191::i;:::-;30292:211;;;;27339:8:::0;:21;;;;;;;;29674:837;;-1:-1:-1;;;;;;;;29674:837:0:o;27932:127::-;16790:13;:11;:13::i;:::-;28016:22:::1;::::0;;;::::1;;::::0;;;:16:::1;:22;::::0;;;;:35;;;::::1;::::0;::::1;;::::0;;;::::1;::::0;;27932:127::o;17803:201::-;16790:13;:11;:13::i;:::-;17892:22:::1;::::0;::::1;17884:73;;;::::0;::::1;::::0;;7013:2:1;17884:73:0::1;::::0;::::1;6995:21:1::0;7052:2;7032:18;;;7025:30;7091:34;7071:18;;;7064:62;7162:8;7142:18;;;7135:36;7188:19;;17884:73:0::1;6811:402:1::0;17884:73:0::1;17968:28;17987:8;17968:18;:28::i;:::-;17803:201:::0;:::o;45482:672::-;45664:14;;;;45650:10;:28;45628:140;;;;;;;7420:2:1;45628:140:0;;;7402:21:1;7459:2;7439:18;;;7432:30;7498:34;7478:18;;;7471:62;7569:32;7549:18;;;7542:60;7619:19;;45628:140:0;7218:426:1;45628:140:0;45779:13;45810:1;45795:12;:16;:46;;45829:12;45795:46;;;45814:12;45795:46;45779:62;;45883:1;45874:6;:10;45852:117;;;;;;;7851:2:1;45852:117:0;;;7833:21:1;7890:2;7870:18;;;7863:30;7929:34;7909:18;;;7902:62;8000:27;7980:18;;;7973:55;8045:19;;45852:117:0;7649:421:1;45852:117:0;45982:14;:40;;;;25492:42;45982:40;;;:14;46051:27;;;;46062:4;46051:27;:::i;:::-;46033:45;-1:-1:-1;46089:57:0;:28;;;46118:10;46138:6;46089:28;:57::i;:::-;45617:537;;45482:672;;;;:::o;30856:2430::-;31071:17;;31128:25;;;25404:42;31128:25;:95;;31186:37;;;;;31212:10;31186:37;;;3108:74:1;31186:25:0;;;;;;3081:18:1;;31186:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;31128:95;;;31169:1;31128:95;31101:122;-1:-1:-1;31234:25:0;31262:26;;;25404:42;31262:26;:107;;31339:30;;;;;:26;3126:55:1;;;31339:30:0;;;3108:74:1;31339:26:0;;;;;3081:18:1;;31339:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;31262:107;;;31312:2;31304:19;;;31262:107;31234:135;-1:-1:-1;31405:8:0;31382:20;;31487:31;31512:5;62203:4;62197:11;;62235:15;;;62222:29;;;62265:20;;;62313:11;;62362:17;;;62357:2;62345:15;;62338:42;62197:11;62056:342;31487:31;31470:48;;31533:859;62645:13;;62700:2;62688:15;;62682:22;-1:-1:-1;31533:859:0;;;31580:17;31600:18;:6;62958:13;;63001:1;62992:11;63024:10;;63048:19;;63024:10;62843:242;31600:18;31580:38;;31641:11;:16;;31656:1;31641:16;31637:714;;31682:18;31703:22;31718:6;31703:14;:22::i;:::-;31682:43;;31752:4;31760:1;31752:9;31748:40;;31778:10;31763:25;;31748:40;31659:149;31637:714;;;31818:11;:16;;31833:1;31818:16;31814:537;;31857:34;31874:6;31882:8;31857:16;:34::i;:::-;31814:537;;;31919:11;:16;;31934:1;31919:16;31915:436;;31960:18;31981:21;31995:6;31981:13;:21::i;31915:436::-;32095:11;:16;;32110:1;32095:16;32091:260;;32113:22;32128:6;32113:14;:22::i;32091:260::-;32163:11;:16;;32178:1;32163:16;32159:192;;32181:26;32200:6;32181:18;:26::i;32159:192::-;32235:11;:16;;32250:1;32235:16;32231:120;;32253:28;32265:7;32274:6;32253:11;:28::i;32231:120::-;32305:46;;;;;8726:2:1;32305:46:0;;;8708:21:1;8765:2;8745:18;;;8738:30;8804:34;8784:18;;;8777:62;8875:6;8855:18;;;8848:34;8899:19;;32305:46:0;8524:400:1;32231:120:0;32370:6;;;:::i;:::-;;;31561:831;31533:859;;;-1:-1:-1;32415:22:0;;-1:-1:-1;32440:25:0;;;25404:42;32440:25;:95;;32498:37;;;;;32524:10;32498:37;;;3108:74:1;32498:25:0;;;;;;3081:18:1;;32498:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;32440:95;;;32481:1;32440:95;32415:120;-1:-1:-1;32597:16:0;32568:25;32585:8;32415:120;32568:25;:::i;:::-;:45;;32546:142;;;;;;;9650:2:1;32546:142:0;;;9632:21:1;9689:2;9669:18;;;9662:30;9728:34;9708:18;;;9701:62;9799:17;9779:18;;;9772:45;9834:19;;32546:142:0;9448:411:1;32546:142:0;32701:23;32727:26;;;25404:42;32727:26;:107;;32804:30;;;;;:26;3126:55:1;;;32804:30:0;;;3108:74:1;32804:26:0;;;;;3081:18:1;;32804:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;32727:107;;;32777:2;32769:19;;;32727:107;32701:133;-1:-1:-1;32867:32:0;32887:12;32867:17;:32;:::i;:::-;32849:15;:50;32845:174;;;32969:35;32987:17;32969:15;:35;:::i;:::-;32921:98;;;;;;;;;2901:25:1;;2889:2;2874:18;;2755:177;32845:174:0;33044:35;33062:17;33044:15;:35;:::i;:::-;33097:181;;;;10246:55:1;;;10228:74;;10333:2;10318:18;;10311:34;;;10361:18;;;10354:34;;;10419:2;10404:18;;10397:34;;;33032:47:0;;-1:-1:-1;33097:181:0;;;;;;;;33117:10;;33097:181;;10215:3:1;10200:19;33097:181:0;;;;;;;31090:2196;;;;;30856:2430;;;;;;;;:::o;17069:132::-;16950:7;16977:6;17133:23;16977:6;15559:10;17133:23;17125:68;;;;;;;10644:2:1;17125:68:0;;;10626:21:1;;;10663:18;;;10656:30;10722:34;10702:18;;;10695:62;10774:18;;17125:68:0;10442:356:1;18164:191:0;18238:16;18257:6;;;18274:17;;;;;;;;;;18307:40;;18257:6;;;;;;;18307:40;;18238:16;18307:40;18227:128;18164:191;:::o;19236:177::-;19346:58;;11007:42:1;10995:55;;19346:58:0;;;10977:74:1;11067:18;;;11060:34;;;19319:86:0;;19339:5;;19369:23;;10950:18:1;;19346:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19319:19;:86::i;:::-;19236:177;;;:::o;34447:394::-;34520:19;34552:13;34568:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;34568:20;34613:38;;;;;34645:4;34613:38;;;3108:74:1;34552:36:0;;-1:-1:-1;34613:23:0;;;;;;3081:18:1;;34613:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34599:52;-1:-1:-1;34691:15:0;;34687:37;;34723:1;34708:16;;;;34687:37;34773:60;34791:6;34807:4;34814:5;34821:11;34773:17;:60::i;:::-;34541:300;34447:394;;;:::o;35089:194::-;35171:13;35187:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;35187:20;35171:36;;35218:57;35236:6;35244:10;35256:5;35263:11;35218:17;:57::i;34038:227::-;34156:21;34188:69;34206:6;34222:4;25404:42;34156:21;34188:17;:69::i;:::-;34038:227;;;:::o;35579:159::-;35638:13;35654:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;35654:20;35638:36;;35685:45;35690:6;25578:42;35721:5;35728:1;35685:4;:45::i;:::-;35627:111;35579:159;:::o;35893:362::-;35956:13;35972:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;35972:20;36025:40;;;;;:18;11358:15:1;;;36025:40:0;;;11340:34:1;36059:4:0;11390:18:1;;;11383:43;35956:36:0;;-1:-1:-1;36003:19:0;;36025:8;:18;;;;11252::1;;36025:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36003:62;-1:-1:-1;36105:15:0;;36101:37;;36122:16;;36101:37;36187:60;36205:6;36221:4;36228:5;36235:11;36187:17;:60::i;33415:484::-;33488:13;33504:17;:6;64302:13;;64345:2;64336:12;64369:10;;64393:19;;64369:10;64186:244;33504:17;33488:33;;33532:16;33551:17;:6;64302:13;;64345:2;64336:12;64369:10;;64393:19;;64369:10;64186:244;33551:17;33532:36;;33579:7;33589:18;:6;62958:13;;63001:1;62992:11;63024:10;;63048:19;;63024:10;62843:242;33589:18;33579:28;;33618:9;33630:20;:6;64302:13;;64345:2;64336:12;64369:10;;64393:19;;64369:10;64186:244;33630:20;33618:32;;33661:9;33673:20;:6;64302:13;;64345:2;64336:12;64369:10;;64393:19;;64369:10;64186:244;33673:20;33661:32;-1:-1:-1;33704:187:0;:32;;;33751:10;33784:4;33804:5;33824:8;33847:1;33863;33661:32;33704;:187::i;:::-;33477:422;;;;;33415:484;;:::o;23559:649::-;23983:23;24009:69;24037:4;24009:69;;;;;;;;;;;;;;;;;24017:5;24009:27;;;;:69;;;;;:::i;:::-;23983:95;;24097:10;:17;24118:1;24097:22;:56;;;;24134:10;24123:30;;;;;;;;;;;;:::i;:::-;24089:111;;;;;;;11889:2:1;24089:111:0;;;11871:21:1;11928:2;11908:18;;;11901:30;11967:34;11947:18;;;11940:62;12038:12;12018:18;;;12011:40;12068:19;;24089:111:0;11687:406:1;36568:545:0;36725:9;36737:18;:6;62958:13;;63001:1;62992:11;63024:10;;63048:19;;63024:10;62843:242;36737:18;36725:30;;36796:9;36791:304;36815:3;36811:7;;:1;:7;36791:304;;;36844:12;36859:19;:6;63294:13;;63337:1;63328:11;63360:10;;63384:19;;63360:10;63177:244;36859:19;36959:16;36915:19;;;;;36914:61;37004:21;;;;;36844:34;;-1:-1:-1;37044:35:0;37049:6;37057:4;37063:7;36914:61;37044:4;:35::i;:::-;-1:-1:-1;;36820:3:0;;36791:304;;37339:705;37480:14;37497:18;:6;62958:13;;63001:1;62992:11;63024:10;;63048:19;;63024:10;62843:242;37497:18;37480:35;;37530:8;:13;;37542:1;37530:13;37526:510;;37545:42;37555:6;37563:4;37569:7;37578:8;37545:9;:42::i;:::-;37526:510;;;37607:8;:13;;37619:1;37607:13;37603:433;;37622:42;37632:6;37640:4;37646:7;37655:8;37622:9;:42::i;37603:433::-;37684:8;:13;;37696:1;37684:13;37680:356;;37699:43;37710:6;37718:4;37724:7;37733:8;37699:10;:43::i;37680:356::-;37762:8;:13;;37774:1;37762:13;37758:278;;37777:44;37789:6;37797:4;37803:7;37812:8;37777:11;:44::i;37758:278::-;37841:8;:13;;37853:1;37841:13;37837:199;;37856:44;37868:6;37876:4;37882:7;37891:8;37856:11;:44::i;37837:199::-;37920:8;:13;;37932:1;37920:13;37916:120;;37935:42;37945:6;37953:4;37959:7;37968:8;37935:9;:42::i;37916:120::-;37993:43;;;;;12489:2:1;37993:43:0;;;12471:21:1;12528:2;12508:18;;;12501:30;12567:34;12547:18;;;12540:62;12638:3;12618:18;;;12611:31;12659:19;;37993:43:0;12287:397:1;37916:120:0;37469:575;37339:705;;;;:::o;22682:486::-;22939:19;;;;;:12;3126:55:1;;;22939:19:0;;;3108:74:1;22917:19:0;;22939:12;;;;;;3081:18:1;;22939:19:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22969:54;;;;;:12;13079:15:1;;;22969:54:0;;;13061:34:1;13131:15;;;13111:18;;;13104:43;13163:18;;;13156:34;;;13206:18;;;13199:34;;;13282:4;13270:17;;13249:19;;;13242:46;13304:19;;;13297:35;;;13348:19;;;13341:35;;;22917:41:0;;-1:-1:-1;22969:12:0;;;;;;12972:19:1;;22969:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;23055:19:0;;;;;:12;3126:55:1;;;23055:19:0;;;3108:74:1;23034:18:0;;-1:-1:-1;23055:12:0;;;-1:-1:-1;23055:12:0;;3081:18:1;;23055:19:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23034:40;-1:-1:-1;23107:15:0;:11;23121:1;23107:15;:::i;:::-;23093:10;:29;23085:75;;;;;;;13589:2:1;23085:75:0;;;13571:21:1;13628:2;13608:18;;;13601:30;13667:34;13647:18;;;13640:62;13738:3;13718:18;;;13711:31;13759:19;;23085:75:0;13387:397:1;23085:75:0;22906:262;;22682:486;;;;;;;;:::o;9418:229::-;9555:12;9587:52;9609:6;9617:4;9623:1;9626:12;9587:21;:52::i;:::-;9580:59;9418:229;-1:-1:-1;;;;9418:229:0:o;41454:1319::-;41600:12;41615:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;41615:20;41600:35;;41646:15;41664:18;:6;62958:13;;63001:1;62992:11;63024:10;;63048:19;;63024:10;62843:242;41664:18;41646:36;;41693:10;41706:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;41706:20;41693:33;;41737:10;41750:19;:6;63630:13;;63673:1;63664:11;63696:10;;63720:19;;63696:10;63513:244;41750:19;41737:32;-1:-1:-1;41829:4:0;41813:21;;;;41809:197;;41849:44;:28;;;41878:4;41884:8;41849:28;:44::i;:::-;41809:197;;;41921:10;41913:18;;;;41909:97;;41946:60;:32;;;41979:10;41991:4;41997:8;41946:32;:60::i;:::-;42020:10;42032;42063:4;42048:32;;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42019:63;;;;;;;;;42106:1;42101:2;:6;:16;;;;;42116:1;42111:2;:6;42101:16;42093:48;;;;;;;14639:2:1;42093:48:0;;;14621:21:1;14678:2;14658:18;;;14651:30;14717:21;14697:18;;;14690:49;14756:18;;42093:48:0;14437:343:1;42093:48:0;42153:17;42172:18;42194:9;:14;;42207:1;42194:14;:62;;42249:2;42253;42194:62;;;42225:2;42229;42194:62;42278:31;;;;;:25;3126:55:1;;;42278:31:0;;;3108:74:1;42152:104:0;;-1:-1:-1;42152:104:0;;-1:-1:-1;42152:104:0;;42278:25;;;;;3081:18:1;;42278:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:43;;;;:::i;:::-;42267:54;-1:-1:-1;42369:23:0;42407:15;42419:3;42407:9;:15;:::i;:::-;42395:28;;;;:8;:28;:::i;:::-;42369:54;-1:-1:-1;42434:17:0;42369:54;42501:21;:9;42513;42501:21;:::i;:::-;:39;;;;:::i;:::-;42455:28;42473:10;42455:15;:28;:::i;:::-;42454:87;;;;:::i;:::-;42434:107;;42553:18;42573;42595:9;:14;;42608:1;42595:14;:92;;42665:9;42684:1;42595:92;;;42634:1;42638:9;42595:92;42752:12;;;42762:1;42752:12;;;;;;;;;42698:67;;;;42552:135;;-1:-1:-1;42552:135:0;-1:-1:-1;42698:25:0;;;;;;:67;;42552:135;;;;42748:2;;42698:67;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41589:1184;;;;;;;;;;;;41454:1319;;;;:::o;43658:904::-;43804:12;43819:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;43819:20;43804:35;;43850:15;43889:1;43868:18;:6;62958:13;;63001:1;62992:11;63024:10;;63048:19;;63024:10;62843:242;43868:18;:22;;;43850:40;;43901:17;43921:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;43921:20;43901:40;-1:-1:-1;43966:10:0;43958:18;;;;43954:181;;43991:144;:32;;;44042:10;44079:4;44111:8;43991:32;:144::i;:::-;44148:14;:21;;;;;;;;;;;;;44180:25;44220:9;44244:10;44276:8;44244:10;44300:52;;44334:18;44351:1;26064:49;44334:18;:::i;:::-;44300:52;;;44313:18;25899:10;44330:1;44313:18;:::i;:::-;44367:19;;;3138:42:1;3126:55;;44367:19:0;;;3108:74:1;3081:18;44367:19:0;;;;;;;;;;;;44180:217;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;44430:14:0;;:41;:14;25492:42;44430:41;44408:127;;;;;;;17959:2:1;44408:127:0;;;17941:21:1;17998:2;17978:18;;;17971:30;18037:34;18017:18;;;18010:62;18108:6;18088:18;;;18081:34;18132:19;;44408:127:0;17757:400:1;38311:1193:0;38458:22;38483:18;:6;62958:13;;63001:1;62992:11;63024:10;;63048:19;;63024:10;62843:242;38483:18;38458:43;;38512:10;38525:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;38525:20;38512:33;-1:-1:-1;38581:1:0;38562:20;;;:25;;38558:939;;38632:17;38652:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;38652:20;38632:40;-1:-1:-1;38710:1:0;38691:20;;38715:1;38691:25;38687:93;;38741:9;38735:24;;;38768:8;38735:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38687:93;38799:19;;;38813:4;38799:19;38795:86;;38837:44;:30;;;38868:2;38872:8;38837:30;:44::i;:::-;38589:304;38558:939;;;38967:1;38948:20;;38972:1;38948:25;38944:330;;39006:10;38998:18;;;;38994:212;;39039:167;:32;;;39098:10;39143:4;39175:8;39039:32;:167::i;:::-;39225:33;;;;;;;;2901:25:1;;;39225:23:0;;;;;;2874:18:1;;39225:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38944:330;39289:12;39315:2;39307:16;;39332:8;39307:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39288:58;;;39387:7;39361:124;;;;;;;18364:2:1;39361:124:0;;;18346:21:1;18403:2;18383:18;;;18376:30;18442:34;18422:18;;;18415:62;18513:25;18493:18;;;18486:53;18556:19;;39361:124:0;18162:419:1;39762:1440:0;39910:15;39928:18;:6;62958:13;;63001:1;62992:11;63024:10;;63048:19;;63024:10;62843:242;39928:18;39910:36;;39957:10;39970:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;39970:20;39957:33;-1:-1:-1;40007:13:0;;;;40003:1192;;40177:4;40161:21;;;;40157:626;;40201:57;:28;;;40238:8;40249;40201:28;:57::i;:::-;40157:626;;;40290:10;40282:18;;;;40278:505;;40319:155;:32;;;40374:10;40415:8;40447;40319:32;:155::i;40278:505::-;40735:24;;;;;:15;3126:55:1;;;40735:24:0;;;3108:74:1;40735:8:0;:15;;;;3081:18:1;;40735:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:32;40673:30;;;;;:21;3126:55:1;;;40673:30:0;;;3108:74:1;40605:162:0;;;;;40673:8;:21;;;;3081:18:1;;40673:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:38;;;;;40605:44;;;;;:25;40639:8;3126:55:1;;40605:44:0;;;3108:74:1;40605:106:0;;;;;:25;;;;;3081:18:1;;40605:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:106;;;;:::i;:::-;:162;;;;:::i;:::-;40573:194;;40278:505;40797:61;;;;;:16;20502:15:1;;;40797:61:0;;;20484:34:1;40797:8:0;:16;;20534:18:1;;;20527:43;;;20606:15;;;20586:18;;;20579:43;20638:18;;;20631:34;;;40856:1:0;20681:19:1;;;20674:35;40797:16:0;;;20395:19:1;;40797:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;40003:1192;;;40928:29;;;;40924:186;;40978:57;;;;;:17;21280:15:1;;;40978:57:0;;;21262:34:1;21332:15;;;21312:18;;;21305:43;41019:4:0;21364:18:1;;;21357:43;21416:18;;;21409:34;;;40978:8:0;:17;;;;21173:19:1;;40978:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40924:186;;;41068:42;;;;;:18;11358:15:1;;;41068:42:0;;;11340:34:1;41104:4:0;11390:18:1;;;11383:43;41068:8:0;:18;;;;11252::1;;41068:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41057:53;;40924:186;41125:58;;;;;:17;20502:15:1;;;41125:58:0;;;20484:34:1;41160:4:0;20534:18:1;;;20527:43;20606:15;;;20586:18;;;20579:43;41171:1:0;20638:18:1;;;20631:34;20681:19;;;20674:35;;;41125:8:0;:17;;;;20395:19:1;;41125:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;39899:1303;;39762:1440;;;;:::o;43006:405::-;43154:12;43169:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;43169:20;65339:13;;65382:2;65373:12;;;65413:10;;65452:16;;;;65437:32;;43154:35;;-1:-1:-1;43259:29:0;;;;43255:110;;43305:48;;;;;:17;21280:15:1;;;43305:48:0;;;21262:34:1;21332:15;;;21312:18;;;21305:43;21384:15;;;21364:18;;;21357:43;21416:18;;;21409:34;;;43305:8:0;:17;;;;21173:19:1;;43305:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43255:110;43377:26;;;;;:16;;;;;;:26;;43394:8;;43377:26;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;48560:2052::-;48706:12;48721:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;48721:20;48706:35;;48752:14;48769:18;:6;62958:13;;63001:1;62992:11;63024:10;;63048:19;;63024:10;62843:242;48769:18;48752:35;;48798:16;48822:18;:6;62958:13;;63001:1;62992:11;63024:10;;63048:19;;63024:10;62843:242;48822:18;48798:43;;;;48852:14;48874:18;:6;62958:13;;63001:1;62992:11;63024:10;;63048:19;;63024:10;62843:242;48874:18;48852:41;;;;48904:10;48917:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;48917:20;48904:33;;48948:16;48967:20;:6;64982:13;;65025:2;65016:12;65049:10;;65073:19;;65049:10;64863:247;48967:20;48948:39;-1:-1:-1;49000:17:0;49032:25;;;;;49028:1149;;49086:156;;;;;22504:2:1;22493:22;;;49086:156:0;;;22475:41:1;22552:22;;;22532:18;;;22525:50;22591:18;;;22584:34;;;49226:1:0;22634:18:1;;;22627:34;49086:21:0;;;;;;49116:8;;22447:19:1;;49086:156:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49074:168;;49028:1149;;;49287:10;49279:18;;;;49275:192;;49316:151;:32;;;49371:10;49412:4;49440:8;49316:32;:151::i;:::-;49482:43;:27;;;49510:4;49516:8;49482:27;:43::i;:::-;;49544:8;:13;;49556:1;49544:13;49540:626;;49588:157;;;;;22504:2:1;22493:22;;;49588:157:0;;;22475:41:1;22552:22;;;22532:18;;;22525:50;22591:18;;;22584:34;;;49725:1:0;22634:18:1;;;22627:34;49588:21:0;;;;;;22447:19:1;;49588:157:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;49540:626::-;49808:81;;;;;49865:4;49808:81;;;3108:74:1;49784:21:0;;49808:26;;;;;;3081:18:1;;49808:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49908:60;;;;;22504:2:1;22493:22;;;49908:60:0;;;22475:41:1;22552:22;;;22532:18;;;22525:50;22591:18;;;22584:34;;;49966:1:0;22634:18:1;;;22627:34;49784:105:0;;-1:-1:-1;49908:27:0;;;;;;22447:19:1;;49908:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;50010:81:0;;;;;50067:4;50010:81;;;3108:74:1;49987:20:0;;-1:-1:-1;50010:26:0;;;;-1:-1:-1;50010:26:0;;3081:18:1;;50010:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49987:104;-1:-1:-1;50122:28:0;50137:13;49987:104;50122:28;:::i;:::-;50110:40;;49765:401;;49540:626;50193:19;;;50207:4;50193:19;50189:416;;50233:26;;;;;50229:365;;50281:12;50307:2;50299:16;;50324:9;50299:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50280:59;;;50388:7;50358:135;;;;;;;22874:2:1;50358:135:0;;;22856:21:1;22913:2;22893:18;;;22886:30;22952:34;22932:18;;;22925:62;23023:24;23003:18;;;22996:52;23065:19;;50358:135:0;22672:418:1;50358:135:0;50261:248;50229:365;;;50534:44;:29;;;50564:2;50568:9;50534:29;:44::i;:::-;48695:1917;;;;;;;48560:2052;;;;:::o;10504:455::-;10674:12;10732:5;10707:21;:30;;10699:81;;;;;;;23297:2:1;10699:81:0;;;23279:21:1;23336:2;23316:18;;;23309:30;23375:34;23355:18;;;23348:62;23446:8;23426:18;;;23419:36;23472:19;;10699:81:0;23095:402:1;10699:81:0;10792:12;10806:23;10833:6;:11;;10852:5;10859:4;10833:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10791:73;;;;10882:69;10909:6;10917:7;10926:10;10938:12;10882:26;:69::i;:::-;10875:76;10504:455;-1:-1:-1;;;;;;;10504:455:0:o;19658:205::-;19786:68;;24006:42:1;24075:15;;;19786:68:0;;;24057:34:1;24127:15;;24107:18;;;24100:43;24159:18;;;24152:34;;;19759:96:0;;19779:5;;19809:27;;23969:18:1;;19786:68:0;23794:398:1;66548:311:0;66668:4;66705:37;66719:5;66726:7;66735:6;66705:13;:37::i;:::-;:146;;;;66760:32;66774:5;66781:7;66790:1;66760:13;:32::i;:::-;:90;;;;;66813:37;66827:5;66834:7;66843:6;66813:13;:37::i;13077:644::-;13262:12;13291:7;13287:427;;;13319:10;:17;13340:1;13319:22;13315:290;;6958:19;;;;13529:60;;;;;;;24399:2:1;13529:60:0;;;24381:21:1;24438:2;24418:18;;;24411:30;24477:31;24457:18;;;24450:59;24526:18;;13529:60:0;24197:353:1;13529:60:0;-1:-1:-1;13626:10:0;13619:17;;13287:427;13669:33;13677:10;13689:12;13669:7;:33::i;65774:366::-;65983:63;;;65949:19;10995:55:1;;;65983:63:0;;;10977:74:1;11067:18;;;;11060:34;;;65983:63:0;;;;;;;;;;10950:18:1;;;;65983:63:0;;;;;;;;;66006:22;65983:63;;;65949:108;;-1:-1:-1;;;;;;65949:19:0;;;;:108;;65983:63;65949:108;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65913:144;;;;66075:7;:57;;;;-1:-1:-1;66087:11:0;;:16;;:44;;;66118:4;66107:24;;;;;;;;;;;;:::i;:::-;66068:64;65774:366;-1:-1:-1;;;;;;65774:366:0:o;14263:552::-;14424:17;;:21;14420:388;;14656:10;14650:17;14713:15;14700:10;14696:2;14692:19;14685:44;14420:388;14783:12;14776:20;;;;;;;;;;;:::i;14:725:1:-;100:6;108;116;124;177:2;165:9;156:7;152:23;148:32;145:52;;;193:1;190;183:12;145:52;229:9;216:23;206:33;;286:2;275:9;271:18;258:32;248:42;;341:2;330:9;326:18;313:32;364:18;405:2;397:6;394:14;391:34;;;421:1;418;411:12;391:34;459:6;448:9;444:22;434:32;;504:7;497:4;493:2;489:13;485:27;475:55;;526:1;523;516:12;475:55;566:2;553:16;592:2;584:6;581:14;578:34;;;608:1;605;598:12;578:34;653:7;648:2;639:6;635:2;631:15;627:24;624:37;621:57;;;674:1;671;664:12;621:57;14:725;;;;-1:-1:-1;;705:2:1;697:11;;-1:-1:-1;;;14:725:1:o;744:154::-;830:42;823:5;819:54;812:5;809:65;799:93;;888:1;885;878:12;903:184;955:77;952:1;945:88;1052:4;1049:1;1042:15;1076:4;1073:1;1066:15;1092:777;1134:5;1187:3;1180:4;1172:6;1168:17;1164:27;1154:55;;1205:1;1202;1195:12;1154:55;1241:6;1228:20;1267:18;1304:2;1300;1297:10;1294:36;;;1310:18;;:::i;:::-;1444:2;1438:9;1506:4;1498:13;;1349:66;1494:22;;;1518:2;1490:31;1486:40;1474:53;;;1542:18;;;1562:22;;;1539:46;1536:72;;;1588:18;;:::i;:::-;1628:10;1624:2;1617:22;1663:2;1655:6;1648:18;1709:3;1702:4;1697:2;1689:6;1685:15;1681:26;1678:35;1675:55;;;1726:1;1723;1716:12;1675:55;1790:2;1783:4;1775:6;1771:17;1764:4;1756:6;1752:17;1739:54;1837:1;1830:4;1825:2;1817:6;1813:15;1809:26;1802:37;1857:6;1848:15;;;;;;1092:777;;;;:::o;1874:876::-;1987:6;1995;2003;2011;2019;2027;2080:3;2068:9;2059:7;2055:23;2051:33;2048:53;;;2097:1;2094;2087:12;2048:53;2136:9;2123:23;2155:31;2180:5;2155:31;:::i;:::-;2205:5;-1:-1:-1;2257:2:1;2242:18;;2229:32;;-1:-1:-1;2313:2:1;2298:18;;2285:32;2326:33;2285:32;2326:33;:::i;:::-;2378:7;-1:-1:-1;2432:2:1;2417:18;;2404:32;;-1:-1:-1;2488:3:1;2473:19;;2460:33;2502;2460;2502;:::i;:::-;2554:7;-1:-1:-1;2612:3:1;2597:19;;2584:33;2640:18;2629:30;;2626:50;;;2672:1;2669;2662:12;2626:50;2695:49;2736:7;2727:6;2716:9;2712:22;2695:49;:::i;:::-;2685:59;;;1874:876;;;;;;;;:::o;3424:1095::-;3563:6;3571;3579;3587;3595;3603;3611;3619;3672:3;3660:9;3651:7;3647:23;3643:33;3640:53;;;3689:1;3686;3679:12;3640:53;3728:9;3715:23;3747:31;3772:5;3747:31;:::i;:::-;3797:5;-1:-1:-1;3849:2:1;3834:18;;3821:32;;-1:-1:-1;3905:2:1;3890:18;;3877:32;3918:33;3877:32;3918:33;:::i;:::-;3970:7;-1:-1:-1;4024:2:1;4009:18;;3996:32;;-1:-1:-1;4080:3:1;4065:19;;4052:33;4094;4052;4094;:::i;:::-;4146:7;-1:-1:-1;4200:3:1;4185:19;;4172:33;;-1:-1:-1;4257:3:1;4242:19;;4229:33;4271;4229;4271;:::i;:::-;4323:7;-1:-1:-1;4381:3:1;4366:19;;4353:33;4409:18;4398:30;;4395:50;;;4441:1;4438;4431:12;4395:50;4464:49;4505:7;4496:6;4485:9;4481:22;4464:49;:::i;:::-;4454:59;;;3424:1095;;;;;;;;;;;:::o;4524:118::-;4610:5;4603:13;4596:21;4589:5;4586:32;4576:60;;4632:1;4629;4622:12;4647:382;4712:6;4720;4773:2;4761:9;4752:7;4748:23;4744:32;4741:52;;;4789:1;4786;4779:12;4741:52;4828:9;4815:23;4847:31;4872:5;4847:31;:::i;:::-;4897:5;-1:-1:-1;4954:2:1;4939:18;;4926:32;4967:30;4926:32;4967:30;:::i;:::-;5016:7;5006:17;;;4647:382;;;;;:::o;5034:247::-;5093:6;5146:2;5134:9;5125:7;5121:23;5117:32;5114:52;;;5162:1;5159;5152:12;5114:52;5201:9;5188:23;5220:31;5245:5;5220:31;:::i;:::-;5270:5;5034:247;-1:-1:-1;;;5034:247:1:o;8335:184::-;8405:6;8458:2;8446:9;8437:7;8433:23;8429:32;8426:52;;;8474:1;8471;8464:12;8426:52;-1:-1:-1;8497:16:1;;8335:184;-1:-1:-1;8335:184:1:o;8929:::-;8981:77;8978:1;8971:88;9078:4;9075:1;9068:15;9102:4;9099:1;9092:15;9118:195;9157:3;9188:66;9181:5;9178:77;9175:103;;9258:18;;:::i;:::-;-1:-1:-1;9305:1:1;9294:13;;9118:195::o;9318:125::-;9383:9;;;9404:10;;;9401:36;;;9417:18;;:::i;:::-;9318:125;;;;:::o;9864:128::-;9931:9;;;9952:11;;;9949:37;;;9966:18;;:::i;11437:245::-;11504:6;11557:2;11545:9;11536:7;11532:23;11528:32;11525:52;;;11573:1;11570;11563:12;11525:52;11605:9;11599:16;11624:28;11646:5;11624:28;:::i;13789:188::-;13868:13;;13921:30;13910:42;;13900:53;;13890:81;;13967:1;13964;13957:12;13982:450;14069:6;14077;14085;14138:2;14126:9;14117:7;14113:23;14109:32;14106:52;;;14154:1;14151;14144:12;14106:52;14177:40;14207:9;14177:40;:::i;:::-;14167:50;;14236:49;14281:2;14270:9;14266:18;14236:49;:::i;:::-;14226:59;;14328:2;14317:9;14313:18;14307:25;14372:10;14365:5;14361:22;14354:5;14351:33;14341:61;;14398:1;14395;14388:12;14341:61;14421:5;14411:15;;;13982:450;;;;;:::o;14785:173::-;14853:8;14894:10;;;14882;;;14878:27;;14917:12;;;14914:38;;;14932:18;;:::i;:::-;14914:38;14785:173;;;;:::o;14963:168::-;15036:9;;;15067;;15084:15;;;15078:22;;15064:37;15054:71;;15105:18;;:::i;15136:274::-;15176:1;15202;15192:189;;15237:77;15234:1;15227:88;15338:4;15335:1;15328:15;15366:4;15363:1;15356:15;15192:189;-1:-1:-1;15395:9:1;;15136:274::o;15415:250::-;15500:1;15510:113;15524:6;15521:1;15518:13;15510:113;;;15600:11;;;15594:18;15581:11;;;15574:39;15546:2;15539:10;15510:113;;;-1:-1:-1;;15657:1:1;15639:16;;15632:27;15415:250::o;15670:329::-;15711:3;15749:5;15743:12;15776:6;15771:3;15764:19;15792:76;15861:6;15854:4;15849:3;15845:14;15838:4;15831:5;15827:16;15792:76;:::i;:::-;15913:2;15901:15;15918:66;15897:88;15888:98;;;;15988:4;15884:109;;15670:329;-1:-1:-1;;15670:329:1:o;16004:481::-;16235:6;16224:9;16217:25;16278:6;16273:2;16262:9;16258:18;16251:34;16333:42;16325:6;16321:55;16316:2;16305:9;16301:18;16294:83;16413:3;16408:2;16397:9;16393:18;16386:31;16198:4;16434:45;16474:3;16463:9;16459:19;16451:6;16434:45;:::i;16490:208::-;16559:42;16634:10;;;16622;;;16618:27;;16657:12;;;16654:38;;;16672:18;;:::i;16703:205::-;16771:42;16833:10;;;16845;;;16829:27;;16868:11;;;16865:37;;;16882:18;;:::i;16913:591::-;17127:4;17156:42;17237:2;17229:6;17225:15;17214:9;17207:34;17291:6;17284:14;17277:22;17272:2;17261:9;17257:18;17250:50;17336:6;17331:2;17320:9;17316:18;17309:34;17391:2;17383:6;17379:15;17374:2;17363:9;17359:18;17352:43;;17432:3;17426;17415:9;17411:19;17404:32;17453:45;17493:3;17482:9;17478:19;17470:6;17453:45;:::i;17509:243::-;17586:6;17594;17647:2;17635:9;17626:7;17622:23;17618:32;17615:52;;;17663:1;17660;17653:12;17615:52;-1:-1:-1;;17686:16:1;;17742:2;17727:18;;;17721:25;17686:16;;17721:25;;-1:-1:-1;17509:243:1:o;18586:192::-;18665:13;;18718:34;18707:46;;18697:57;;18687:85;;18768:1;18765;18758:12;18783:548;18877:6;18930:2;18918:9;18909:7;18905:23;18901:32;18898:52;;;18946:1;18943;18936:12;18898:52;18979:2;18973:9;19021:2;19013:6;19009:15;19090:6;19078:10;19075:22;19054:18;19042:10;19039:34;19036:62;19033:88;;;19101:18;;:::i;:::-;19137:2;19130:22;19176:40;19206:9;19176:40;:::i;:::-;19168:6;19161:56;19250:49;19295:2;19284:9;19280:18;19250:49;:::i;:::-;19245:2;19233:15;;19226:74;19237:6;18783:548;-1:-1:-1;;;18783:548:1:o;19336:175::-;19414:13;;19467:18;19456:30;;19446:41;;19436:69;;19501:1;19498;19491:12;19516:635;19616:6;19669:2;19657:9;19648:7;19644:23;19640:32;19637:52;;;19685:1;19682;19675:12;19637:52;19718:2;19712:9;19760:2;19752:6;19748:15;19829:6;19817:10;19814:22;19793:18;19781:10;19778:34;19775:62;19772:88;;;19840:18;;:::i;:::-;19876:2;19869:22;19915:39;19944:9;19915:39;:::i;:::-;19907:6;19900:55;19988:48;20032:2;20021:9;20017:18;19988:48;:::i;:::-;19983:2;19975:6;19971:15;19964:73;20070:49;20115:2;20104:9;20100:18;20070:49;:::i;:::-;20065:2;20053:15;;20046:74;20057:6;19516:635;-1:-1:-1;;;19516:635:1:o;22018:217::-;22165:2;22154:9;22147:21;22128:4;22185:44;22225:2;22214:9;22210:18;22202:6;22185:44;:::i;23502:287::-;23631:3;23669:6;23663:13;23685:66;23744:6;23739:3;23732:4;23724:6;23720:17;23685:66;:::i;:::-;23767:16;;;;;23502:287;-1:-1:-1;;23502:287:1:o
Swarm Source
ipfs://66b57539997c8cb99ab953370484ebb43508a94ef324cf6e699d651e5147efa3
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
CELO | 100.00% | $0.336189 | 0.000000000000000001 | <$0.000001 |
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.