Polygon Sponsored slots available. Book your slot here!
More Info
Private Name Tags
ContractCreator
TokenTracker
Loading...
Loading
Contract Name:
BalancerMarketMaker
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; // ==================================================================== // ======================== BalancerMarketMaker.sol =================== // ==================================================================== /** * @title Balancer Stable/Stable Pool Market Maker * @dev Implementation: * Increases and decreases the liquidity */ import { Stabilizer, TransferHelper, ISweep } from "../Stabilizer/Stabilizer.sol"; import { IBalancerPool, IBalancerVault, IAsset, JoinKind, ExitKind } from "../Assets/Interfaces/Balancer/IBalancer.sol"; contract BalancerMarketMaker is Stabilizer { error BadAddress(); error BadSlippage(); event LiquidityAdded(uint256 usdxAmount, uint256 sweepAmount); event LiquidityRemoved(uint256 usdxAmount, uint256 sweepAmount); event SweepPurchased(uint256 sweeAmount); IBalancerPool public pool; IBalancerVault public vault; bytes32 public poolId; IAsset[] public poolAssets; uint8 public sweepIndex; uint8 public usdxIndex; uint8 public bptIndex; uint32 public slippage; uint24 private constant PRECISION = 1e6; constructor( string memory _name, address _sweep, address _usdx, address _oracleUsdx, address _poolAddress, address _borrower ) Stabilizer(_name, _sweep, _usdx, _oracleUsdx, _borrower) { slippage = 5000; // 0.5% pool = IBalancerPool(_poolAddress); vault = IBalancerVault(pool.getVault()); poolId = pool.getPoolId(); (poolAssets, , ) = vault.getPoolTokens(poolId); sweepIndex = findAssetIndex(address(sweep), poolAssets); usdxIndex = findAssetIndex(address(usdx), poolAssets); bptIndex = findAssetIndex(address(pool), poolAssets); } /* ========== Views ========== */ /** * @notice Gets the asset price of AMM * @return the amm usdx amount */ function assetValue() public view override returns (uint256) { uint256 bpt = pool.balanceOf(address(this)); uint256 rate = pool.getRate(); uint256 usdcAmount = (bpt * rate * (10 ** usdx.decimals())) / (10 ** (pool.decimals() * 2)); return _oracleUsdxToUsd(usdcAmount); } function getBuyPrice() public view returns (uint256) { uint256 targetPrice = sweep.targetPrice(); return targetPrice + ((sweep.arbSpread() * targetPrice) / PRECISION); } /* ========== Actions ========== */ function buySweep(uint256 usdxAmount) external nonReentrant returns (uint256 sweepAmount) { sweepAmount = (_oracleUsdxToUsd(usdxAmount) * (10 ** sweep.decimals())) / getBuyPrice(); _borrow(sweepAmount * 2); _addLiquidity(usdxAmount, sweepAmount); TransferHelper.safeTransfer(address(sweep), msg.sender, sweepAmount); emit SweepPurchased(usdxAmount); } function initPool(uint256 usdxAmount, uint256 sweepAmount) external nonReentrant onlyBorrower { address self = address(this); TransferHelper.safeTransferFrom(address(usdx), msg.sender, self, usdxAmount); TransferHelper.safeApprove(address(usdx), address(vault), usdxAmount); TransferHelper.safeApprove(address(sweep), address(vault), sweepAmount); if(sweep.isMintingAllowed()){ _borrow(sweepAmount); } else { TransferHelper.safeTransferFrom(address(sweep), msg.sender, self, sweepAmount); } uint256[] memory amounts = new uint256[](3); amounts[bptIndex] = 2**112; amounts[usdxIndex] = usdxAmount; amounts[sweepIndex] = sweepAmount; bytes memory userData = abi.encode(JoinKind.INIT, amounts); IBalancerVault.JoinPoolRequest memory request = IBalancerVault.JoinPoolRequest(poolAssets, amounts, userData, false); vault.joinPool(poolId, self, self, request); } function _addLiquidity(uint256 usdxAmount, uint256 sweepAmount) internal { address self = address(this); TransferHelper.safeTransferFrom(address(usdx), msg.sender, self, usdxAmount); TransferHelper.safeApprove(address(usdx), address(vault), usdxAmount); TransferHelper.safeApprove(address(sweep), address(vault), sweepAmount); uint256[] memory amounts = new uint256[](3); amounts[usdxIndex] = usdxAmount; amounts[sweepIndex] = sweepAmount; uint256[] memory userDataAmounts = new uint256[](2); userDataAmounts[0] = (sweepIndex > usdxIndex) ? usdxAmount : sweepAmount; userDataAmounts[1] = (sweepIndex > usdxIndex) ? sweepAmount : usdxAmount; uint256 usdxMin = usdxAmount * pool.getTokenRate(address(usdx)) / (10 ** usdx.decimals()); uint256 sweepMin = sweepAmount * pool.getTokenRate(address(sweep)) / (10 ** sweep.decimals()); uint256 minTotalAmountOut = (usdxMin + sweepMin) * (PRECISION - slippage) / PRECISION; bytes memory userData = abi.encode(JoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT, userDataAmounts, minTotalAmountOut); IBalancerVault.JoinPoolRequest memory request = IBalancerVault.JoinPoolRequest(poolAssets, amounts, userData, false); vault.joinPool(poolId, self, self, request); } function addLiquidity(uint256 usdxAmount, uint256 sweepAmount) external nonReentrant onlyBorrower { address self = address(this); if(sweep.isMintingAllowed()){ if(sweepAmount > 0) _borrow(sweepAmount); } else { TransferHelper.safeTransferFrom(address(sweep), msg.sender, self, sweepAmount); } _addLiquidity(usdxAmount, sweepAmount); emit LiquidityAdded(usdxAmount, sweepAmount); } function removeLiquidity(uint256 usdxAmount, uint256 sweepAmount) external nonReentrant onlyBorrower { address self = address(this); uint256 usdxMax = usdxAmount * pool.getTokenRate(address(usdx)) / (10**usdx.decimals()); uint256 sweepMax = sweepAmount * pool.getTokenRate(address(sweep)) / (10**sweep.decimals()); uint256 maxAmountIn = (usdxMax + sweepMax) * (PRECISION + slippage) / PRECISION; uint256[] memory amounts = new uint256[](3); amounts[usdxIndex] = usdxAmount; amounts[sweepIndex] = sweepAmount; uint256[] memory userDataAmounts = new uint256[](2); userDataAmounts[0] = (sweepIndex > usdxIndex) ? usdxAmount : sweepAmount; userDataAmounts[1] = (sweepIndex > usdxIndex) ? sweepAmount : usdxAmount; bytes memory userData = abi.encode(ExitKind.BPT_IN_FOR_EXACT_TOKENS_OUT, userDataAmounts, maxAmountIn); IBalancerVault.ExitPoolRequest memory request = IBalancerVault.ExitPoolRequest(poolAssets, amounts, userData, false); vault.exitPool(poolId, self, self, request); if(sweepAmount > 0) _repay(sweepAmount); emit LiquidityRemoved(usdxAmount, sweepAmount); } function setSlippage(uint32 newSlippage) external nonReentrant onlyBorrower { if(newSlippage > PRECISION) revert BadSlippage(); slippage = newSlippage; } function findAssetIndex(address asset, IAsset[] memory assets) internal pure returns (uint8) { for (uint8 i = 0; i < assets.length; i++) { if ( address(assets[i]) == asset ) return i; } revert BadAddress(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../token/ERC20/extensions/IERC20Metadata.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.0; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; library TransferHelper { /// @notice Transfers tokens from the targeted address to the given destination /// @notice Errors with 'STF' if transfer fails /// @param token The contract address of the token to be transferred /// @param from The originating address from which the tokens will be transferred /// @param to The destination address of the transfer /// @param value The amount to be transferred function safeTransferFrom( address token, address from, address to, uint256 value ) internal { (bool success, bytes memory data) = token.call( abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value) ); require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF'); } /// @notice Transfers tokens from msg.sender to a recipient /// @dev Errors with ST if transfer fails /// @param token The contract address of the token which will be transferred /// @param to The recipient of the transfer /// @param value The value of the transfer function safeTransfer( address token, address to, uint256 value ) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST'); } /// @notice Approves the stipulated contract to spend the given allowance in the given token /// @dev Errors with 'SA' if transfer fails /// @param token The contract address of the token to be approved /// @param to The target of the approval /// @param value The amount of the given token the target will be allowed to spend function safeApprove( address token, address to, uint256 value ) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA'); } /// @notice Transfers ETH to the recipient address /// @dev Fails with `STE` /// @param to The destination of the transfer /// @param value The value to be transferred function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, 'STE'); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; interface IAMM { function swapExactInput( address tokenA, address tokenB, uint24 fee, uint256 amountIn, uint256 amountOutMin ) external returns (uint256); function swap( address tokenA, address tokenB, uint256 amountIn, uint256 amountOutMin, address poolAddress ) external returns (uint256); function buySweep( address token, uint256 amountIn, uint256 amountOutMin ) external returns (uint256); function sellSweep( address token, uint256 amountIn, uint256 amountOutMin ) external returns (uint256); function sequencer() external view returns (address); function pool() external view returns (address); function getTWAPrice() external view returns (uint256 twaPrice); function getPrice() external view returns (uint256 price); function getRate() external view returns (uint256 rate); function getPositions(uint256) external view returns (uint256 usdxAmount, uint256 sweepAmount, uint256 lp); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; import "@openzeppelin/contracts/interfaces/IERC20Metadata.sol"; interface IBalancerGauge { function claim_rewards() external; function deposit(uint256 _amount) external; function withdraw(uint256 _amount) external; function balanceOf(address _address) external view returns(uint256 _balance); } interface IBalancerVault { struct JoinPoolRequest { IAsset[] assets; uint256[] maxAmountsIn; bytes userData; bool fromInternalBalance; } struct ExitPoolRequest { IAsset[] assets; uint256[] minAmountsOut; bytes userData; bool toInternalBalance; } function joinPool(bytes32 poolId, address sender, address recipient, JoinPoolRequest memory request) external payable; function exitPool(bytes32 poolId, address sender, address recipient, ExitPoolRequest memory request) external payable; function getPoolTokens(bytes32 poolId) external view returns (IAsset[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock); function swap(SingleSwap memory singleSwap, FundManagement memory funds, uint256 limit, uint256 deadline) external returns (uint256 amountOut); } interface IAsset { // solhint-disable-previous-line no-empty-blocks } interface IBalancerPool is IERC20Metadata { function getPoolId() external view returns (bytes32); function getVault() external view returns (address); function getRate() external view returns (uint256); function getTokenRate(address) external view returns (uint256); function getScalingFactors() external view returns (uint256[] memory); function getAmplificationParameter() external view returns (uint256, bool, uint256); } struct SingleSwap { bytes32 poolId; SwapKind kind; IAsset assetIn; IAsset assetOut; uint256 amount; bytes userData; } struct FundManagement { address sender; bool fromInternalBalance; address payable recipient; bool toInternalBalance; } interface IComposableStablePoolFactory { function create( string memory name, string memory symbol, IERC20[] memory tokens, uint256 amplificationParameter, IRateProvider[] memory rateProviders, uint256[] memory tokenRateCacheDurations, bool exemptFromYieldProtocolFeeFlag, uint256 swapFeePercentage, address owner, bytes32 salt ) external returns(address poolAddress); } interface IRateProvider { function getRate() external view returns (uint256); } enum JoinKind { INIT, EXACT_TOKENS_IN_FOR_BPT_OUT, TOKEN_IN_FOR_EXACT_BPT_OUT, ALL_TOKENS_IN_FOR_EXACT_BPT_OUT } enum ExitKind { EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, BPT_IN_FOR_EXACT_TOKENS_OUT, EXACT_BPT_IN_FOR_ALL_TOKENS_OUT } enum SwapKind { GIVEN_IN, GIVEN_OUT }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.19; // ========================================================== // ======================= Owned.sol ======================== // ========================================================== import "../Sweep/ISweep.sol"; contract Owned { ISweep public immutable sweep; // Errors error NotGovernance(); error NotMultisigOrGov(); error ZeroAddressDetected(); constructor(address _sweep) { if(_sweep == address(0)) revert ZeroAddressDetected(); sweep = ISweep(_sweep); } modifier onlyGov() { if (msg.sender != sweep.owner()) revert NotGovernance(); _; } modifier onlyMultisigOrGov() { if (msg.sender != sweep.fastMultisig() && msg.sender != sweep.owner()) revert NotMultisigOrGov(); _; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; interface IPriceFeed { function latestAnswer() external view returns (int256); function latestTimestamp() external view returns (uint256); function latestRound() external view returns (uint256); function getAnswer(uint256 roundId) external view returns (int256); function getTimestamp(uint256 roundId) external view returns (uint256); function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); function getRoundData( uint80 _roundId ) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } library ChainlinkLibrary { uint8 constant USD_DECIMALS = 6; function getDecimals(IPriceFeed oracle) internal view returns (uint8) { return oracle.decimals(); } function getPrice(IPriceFeed oracle) internal view returns (uint256) { ( uint80 roundID, int256 price, , uint256 timeStamp, uint80 answeredInRound ) = oracle.latestRoundData(); require(answeredInRound >= roundID, "Old data"); require(timeStamp > 0, "Round not complete"); return uint256(price); } function getPrice( IPriceFeed oracle, IPriceFeed sequencerOracle, uint256 frequency ) internal view returns (uint256) { if (address(sequencerOracle) != address(0)) checkUptime(sequencerOracle); (uint256 roundId, int256 price, , uint256 updatedAt, ) = oracle .latestRoundData(); require(price > 0 && roundId != 0 && updatedAt != 0, "Invalid Price"); if (frequency > 0) require(block.timestamp - updatedAt <= frequency, "Stale Price"); return uint256(price); } function checkUptime(IPriceFeed sequencerOracle) internal view { (, int256 answer, uint256 startedAt, , ) = sequencerOracle .latestRoundData(); require(answer <= 0, "Sequencer Down"); // 0: Sequencer is up, 1: Sequencer is down require(block.timestamp - startedAt > 1 hours, "Grace Period Not Over"); } function convertTokenToToken( uint256 amount0, uint8 token0Decimals, uint8 token1Decimals, IPriceFeed oracle0, IPriceFeed oracle1 ) internal view returns (uint256 amount1) { uint256 price0 = getPrice(oracle0); uint256 price1 = getPrice(oracle1); amount1 = (amount0 * price0 * (10 ** token1Decimals)) / (price1 * (10 ** token0Decimals)); } function convertTokenToUsd( uint256 amount, uint8 tokenDecimals, IPriceFeed oracle ) internal view returns (uint256 amountUsd) { uint8 decimals = getDecimals(oracle); uint256 price = getPrice(oracle); amountUsd = (amount * price * (10 ** USD_DECIMALS)) / 10 ** (decimals + tokenDecimals); } function convertUsdToToken( uint256 amountUsd, uint256 tokenDecimals, IPriceFeed oracle ) internal view returns (uint256 amount) { uint8 decimals = getDecimals(oracle); uint256 price = getPrice(oracle); amount = (amountUsd * 10 ** (decimals + tokenDecimals)) / (price * (10 ** USD_DECIMALS)); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; library OvnMath { uint256 constant BASIS_DENOMINATOR = 1e6; function abs(uint256 x, uint256 y) internal pure returns (uint256) { return (x > y) ? (x - y) : (y - x); } function addBasisPoints( uint256 amount, uint256 basisPoints ) internal pure returns (uint256) { return (amount * (BASIS_DENOMINATOR + basisPoints)) / BASIS_DENOMINATOR; } function reverseAddBasisPoints( uint256 amount, uint256 basisPoints ) internal pure returns (uint256) { return (amount * BASIS_DENOMINATOR) / (BASIS_DENOMINATOR + basisPoints); } function subBasisPoints( uint256 amount, uint256 basisPoints ) internal pure returns (uint256) { return (amount * (BASIS_DENOMINATOR - basisPoints)) / BASIS_DENOMINATOR; } function reverseSubBasisPoints( uint256 amount, uint256 basisPoints ) internal pure returns (uint256) { return (amount * BASIS_DENOMINATOR) / (BASIS_DENOMINATOR - basisPoints); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; // ==================================================================== // ====================== Stabilizer.sol ============================== // ==================================================================== /** * @title Stabilizer * @dev Implementation: * Allows to take debt by minting sweep and repaying by burning sweep * Allows to buy and sell sweep in an AMM * Allows auto invest according the borrower configuration * Allows auto repays by the balancer to control sweep price * Allow liquidate the Asset when is defaulted * Repayments made by burning sweep * EquityRatio = Junior / (Junior + Senior) */ import "../AMM/IAMM.sol"; import "../Common/Owned.sol"; import "../Libraries/Chainlink.sol"; import "../Libraries/OvnMath.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/interfaces/IERC20Metadata.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; contract Stabilizer is Owned, Pausable, ReentrancyGuard { using Math for uint256; IERC20Metadata public usdx; IPriceFeed public oracleUsdx; // Variables string public name; address public borrower; int256 public minEquityRatio; // Minimum Equity Ratio. 10000 is 1% uint256 public sweepBorrowed; uint256 public loanLimit; uint256 public callTime; uint256 public callDelay; // 86400 is 1 day uint256 public callAmount; uint256 public spreadFee; // 10000 is 1% uint256 public spreadDate; string public link; int256 public autoInvestMinRatio; // 10000 is 1% uint256 public autoInvestMinAmount; bool public autoInvestEnabled; bool public settingsEnabled; uint256 public startingTime; uint256 public startingPrice; uint256 public decreaseFactor; // 10000 is 1% uint256 public minLiquidationRatio; // 100000 is 10% bool public auctionAllowed; // Constants for various precisions uint256 private constant DAY_SECONDS = 60 * 60 * 24; // seconds of Day uint256 private constant DAYS_ONE_YEAR = 365; // days of Year uint256 private constant PRECISION = 1e6; uint256 private constant ORACLE_FREQUENCY = 1 days; /* ========== Events ========== */ event Borrowed(uint256 indexed sweepAmount); event Repaid(uint256 indexed sweepAmount); event Withdrawn(address indexed token, uint256 indexed amount); event PayFee(uint256 indexed sweepAmount); event Bought(uint256 indexed sweepAmount); event Sold(uint256 indexed sweepAmount); event BoughtSWEEP(uint256 indexed sweepAmount); event SoldSWEEP(uint256 indexed usdxAmount); event LoanLimitChanged(uint256 loanLimit); event Proposed(address indexed borrower); event Rejected(address indexed borrower); event SweepBorrowedChanged(uint256 indexed sweepAmount); event Liquidated(address indexed user); event AutoCalled(uint256 indexed sweepAmount); event AutoInvested(uint256 indexed sweepAmount); event CallCancelled(uint256 indexed sweepAmount); event ConfigurationChanged( int256 indexed minEquityRatio, uint256 indexed spreadFee, uint256 loanLimit, uint256 decreaseFactor, uint256 callDelay, int256 autoInvestMinRatio, uint256 autoInvestMinAmount, uint256 minLiquidationRatio, bool autoInvestEnabled, bool _auctionAllowed, string url ); /* ========== Errors ========== */ error NotBorrower(); error NotBalancer(); error NotSweep(); error SettingsDisabled(); error OverZero(); error AssetDefaulted(); error AuctionNotActive(); error ActionNotAllowed(); error InvalidMinter(); error NotEnoughBalance(); error EquityRatioExcessed(); error InvalidToken(); error SpreadNotEnough(); error NotDefaulted(); error NotAutoInvest(); error NotAutoInvestMinAmount(); error NotAutoInvestMinRatio(); /* ========== Modifies ========== */ modifier onlyBorrower() { _onlyBorrower(); _; } modifier onlySettingsEnabled() { _onlySettingsEnabled(); _; } modifier validAmount(uint256 amount) { _validAmount(amount); _; } constructor( string memory _name, address _sweep, address _usdx, address _oracleUsdx, address _borrower ) Owned(_sweep) { if (_borrower == address(0)) revert ZeroAddressDetected(); name = _name; usdx = IERC20Metadata(_usdx); oracleUsdx = IPriceFeed(_oracleUsdx); borrower = _borrower; settingsEnabled = true; } /* ========== Views ========== */ /** * @notice Defaulted * @return bool that tells if stabilizer is in default. */ function isDefaulted() public view returns (bool) { return (callDelay > 0 && callAmount > 0 && block.timestamp > callTime) || (sweepBorrowed > 0 && getEquityRatio() < minEquityRatio); } /** * @notice Get Equity Ratio * @return the current equity ratio based in the internal storage. * @dev this value have a precision of 6 decimals. */ function getEquityRatio() public view returns (int256) { uint256 totalValue = currentValue(); if (totalValue == 0) { if (sweepBorrowed > 0) return -1e6; else return 0; } uint256 seniorTrancheInUsd = sweep.convertToUSD(sweepBorrowed); // 1e6 are decimals of the percentage result int256 equityRatio = ((int256(totalValue) - int256(seniorTrancheInUsd)) * 1e6) / int256(totalValue); if (equityRatio < -1e6) equityRatio = -1e6; return equityRatio; } /** * @notice Get Spread Amount * fee = borrow_amount * spread_ratio * (time / time_per_year) * @return uint256 calculated spread amount. */ function accruedFee() public view returns (uint256) { if (sweepBorrowed > 0) { uint256 period = (block.timestamp - spreadDate) / DAY_SECONDS; return (sweepBorrowed * spreadFee * period) / (DAYS_ONE_YEAR * PRECISION); } return 0; } /** * @notice Get Debt Amount * debt = borrow_amount + spread fee * @return uint256 calculated debt amount. */ function getDebt() public view returns (uint256) { return sweepBorrowed + accruedFee(); } /** * @notice Get Current Value * value = sweep balance + usdx balance * @return uint256. */ function currentValue() public view returns (uint256) { (uint256 usdxBalance, uint256 sweepBalance) = _balances(); uint256 sweepInUsd = sweep.convertToUSD(sweepBalance); uint256 usdxInUsd = _oracleUsdxToUsd(usdxBalance); uint256 accruedFeeInUSD = sweep.convertToUSD(accruedFee()); return assetValue() + usdxInUsd + sweepInUsd - accruedFeeInUSD; } /** * @notice Get AMM from Sweep * @return address. */ function amm() public view virtual returns (IAMM) { return IAMM(sweep.amm()); } /** * @notice Get Junior Tranche Value * @return int256 calculated junior tranche amount. */ function getJuniorTrancheValue() external view returns (int256) { uint256 seniorTrancheInUSD = sweep.convertToUSD(sweepBorrowed); uint256 totalValue = currentValue(); return int256(totalValue) - int256(seniorTrancheInUSD); } /** * @notice Returns the SWEEP required to liquidate the stabilizer in the auction. * @return auctionPrice */ function getAuctionAmount() public view returns (uint256) { uint256 minPrice = sweepBorrowed * (PRECISION - minLiquidationRatio) / PRECISION; uint256 timeElapsed = (block.timestamp - startingTime) / 5 minutes; uint256 ratio = timeElapsed * decreaseFactor; if(ratio > PRECISION) return minPrice; uint256 decreaseRatio = PRECISION - ratio; uint256 auctionPrice = (startingPrice * decreaseRatio) / PRECISION; return minPrice > auctionPrice ? minPrice : auctionPrice; } /* ========== Settings ========== */ /** * @notice Pause * @dev Stops investment actions. */ function pause() external onlyMultisigOrGov { _pause(); } /** * @notice Unpause * @dev Start investment actions. */ function unpause() external onlyMultisigOrGov { _unpause(); } /** * @notice Configure intial settings * @param _minEquityRatio The minimum equity ratio can be negative. * @param _spreadFee The fee that the protocol will get for providing the loan when the stabilizer takes debt * @param _loanLimit How much debt a Stabilizer can take in SWEEP. * @param _decreaseFactor A percentage that will be discounted from the price as time passes from the auction start. * @param _callDelay Time in seconds after AutoCall until the Stabilizer gets defaulted if the debt is not paid in that period * @param _autoInvestMinRatio Minimum equity ratio that should be kept to allow the execution of an auto invest * @param _autoInvestMinAmount Minimum amount to be invested to allow the execution of an auto invest * @param _autoInvestEnabled Represents if an auto invest execution is allowed or not * @param _auctionAllowed Represents if an auction is allowed or not * @param _url A URL link to a Web page that describes the borrower and the asset * @dev Sets the initial configuration of the Stabilizer. * This configuration will be analyzed by the protocol and if accepted, * used to include the Stabilizer in the minter's whitelist of Sweep. * The minimum equity ratio can not be less than 1% */ function configure( int256 _minEquityRatio, uint256 _spreadFee, uint256 _loanLimit, uint256 _decreaseFactor, uint256 _callDelay, int256 _autoInvestMinRatio, uint256 _autoInvestMinAmount, uint256 _minLiquidationRatio, bool _autoInvestEnabled, bool _auctionAllowed, string calldata _url ) external onlyBorrower onlySettingsEnabled { minEquityRatio = _minEquityRatio; spreadFee = _spreadFee; loanLimit = _loanLimit; decreaseFactor = _decreaseFactor; callDelay = _callDelay; autoInvestMinRatio = _autoInvestMinRatio; autoInvestMinAmount = _autoInvestMinAmount; minLiquidationRatio = _minLiquidationRatio; autoInvestEnabled = _autoInvestEnabled; auctionAllowed = _auctionAllowed; link = _url; emit ConfigurationChanged( _minEquityRatio, _spreadFee, _loanLimit, decreaseFactor, _callDelay, _autoInvestMinRatio, _autoInvestMinAmount, _minLiquidationRatio, _autoInvestEnabled, _auctionAllowed, _url ); } /** * @notice Changes the account that control the global configuration to the protocol/governance admin * @dev after disable settings by admin * the protocol will evaluate adding the stabilizer to the minter list. */ function propose() external onlyBorrower { settingsEnabled = false; emit Proposed(borrower); } /** * @notice Changes the account that control the global configuration to the borrower * @dev after enable settings for the borrower * he/she should edit the values to align to the protocol requirements */ function reject() external onlyGov { settingsEnabled = true; emit Rejected(borrower); } /* ========== Actions ========== */ /** * @notice Borrows Sweep * Asks the stabilizer to mint a certain amount of sweep token. * @param sweepAmount. * @dev Increases the sweepBorrowed (senior tranche). */ function borrow( uint256 sweepAmount ) public onlyBorrower whenNotPaused validAmount(sweepAmount) nonReentrant { _borrow(sweepAmount); if (getEquityRatio() < minEquityRatio) { revert EquityRatioExcessed(); } } /** * @notice Repays Sweep * Burns the sweep amount to reduce the debt (senior tranche). * @param sweepAmount Amount to be burnt by Sweep. * @dev Decreases the sweep borrowed. */ function repay(uint256 sweepAmount) external onlyBorrower nonReentrant { _repay(sweepAmount); } /** * @notice Pay the spread to the treasury */ function payFee() external onlyBorrower nonReentrant { uint256 spreadAmount = accruedFee(); spreadDate = block.timestamp; uint256 sweepBalance = sweep.balanceOf(address(this)); if (spreadAmount > sweepBalance) revert SpreadNotEnough(); if (spreadAmount > 0) { TransferHelper.safeTransfer( address(sweep), sweep.treasury(), spreadAmount ); emit PayFee(spreadAmount); } } /** * @notice Set Loan Limit. * @param newLoanLimit. * @dev How much debt an Stabilizer can take in SWEEP. */ function setLoanLimit(uint256 newLoanLimit) external { if (msg.sender != sweep.balancer()) revert NotBalancer(); loanLimit = newLoanLimit; emit LoanLimitChanged(newLoanLimit); } /** * @notice Update Sweep Borrowed Amount. * @param amount. */ function updateSweepBorrowed(uint256 amount) external { if (msg.sender != address(sweep)) revert NotSweep(); sweepBorrowed = amount; emit SweepBorrowedChanged(amount); } /** * @notice Auto Call. * @param sweepAmount to repay. * @dev Strategy: * 1) repays debt with SWEEP balance * 2) repays remaining debt by divesting * 3) repays remaining debt by buying on SWEEP in the AMM */ function autoCall( uint256 sweepAmount, uint256, uint256 slippage ) external nonReentrant { if (msg.sender != sweep.balancer()) revert NotBalancer(); (uint256 usdxBalance, uint256 sweepBalance) = _balances(); uint256 repayAmount = sweepAmount.min(getDebt()); if (callDelay > 0) { callTime = block.timestamp + callDelay; callAmount = repayAmount; } if (sweepBalance < repayAmount) { uint256 missingSweep = repayAmount - sweepBalance; uint256 sweepInUsd = sweep.convertToUSD(missingSweep); uint256 missingUsdx = _oracleUsdToUsdx(sweepInUsd); if (missingUsdx > usdxBalance) { _divest(missingUsdx - usdxBalance, slippage); } if (usdx.balanceOf(address(this)) > 0) { _buy(missingUsdx, slippage); } } if (sweep.balanceOf(address(this)) > 0 && repayAmount > 0) { _repay(repayAmount); } emit AutoCalled(sweepAmount); } /** * @notice Cancel Call * @dev Cancels the auto call request by clearing variables for an asset * that has a callDelay: meaning that it does not autorepay. */ function cancelCall() external { if (msg.sender != sweep.balancer()) revert NotBalancer(); callAmount = 0; callTime = 0; emit CallCancelled(callAmount); } /** * @notice Auto Invest. * @param sweepAmount to mint. * @param slippage. */ function autoInvest( uint256 sweepAmount, uint256, uint256 slippage ) external nonReentrant { if (msg.sender != sweep.balancer()) revert NotBalancer(); if (!autoInvestEnabled) revert NotAutoInvest(); if (sweepAmount < autoInvestMinAmount) revert NotAutoInvestMinAmount(); _borrow(sweepAmount); uint256 usdxAmount = _sell(sweepAmount, slippage); _invest(usdxAmount, 0, slippage); if (getEquityRatio() < autoInvestMinRatio){ revert NotAutoInvestMinRatio(); } emit AutoInvested(sweepAmount); } /** * @notice Buy * Buys sweep amount from the stabilizer's balance to the AMM (swaps USDX to SWEEP). * @param usdxAmount Amount to be changed in the AMM. * @param slippage Minimum amount out. * @dev Increases the sweep balance and decrease usdx balance. */ function buySweepOnAMM( uint256 usdxAmount, uint256 slippage ) external onlyBorrower whenNotPaused nonReentrant returns (uint256 sweepAmount) { sweepAmount = _buy(usdxAmount, slippage); emit Bought(sweepAmount); } /** * @notice Sell Sweep * Sells sweep amount from the stabilizer's balance to the AMM (swaps SWEEP to USDX). * @param sweepAmount. * @param slippage Minimum amount out. * @dev Decreases the sweep balance and increase usdx balance */ function sellSweepOnAMM( uint256 sweepAmount, uint256 slippage ) external onlyBorrower whenNotPaused nonReentrant returns (uint256 usdxAmount) { usdxAmount = _sell(sweepAmount, slippage); emit Sold(sweepAmount); } /** * @notice Buy Sweep with Stabilizer * Buys sweep amount from the stabilizer's balance to the Borrower (swaps USDX to SWEEP). * @param usdxAmount. * @dev Decreases the sweep balance and increase usdx balance */ function swapUsdxToSweep(uint256 usdxAmount) public onlyBorrower whenNotPaused validAmount(usdxAmount) nonReentrant returns (uint256 sweepAmount) { uint256 usdxInUsd = _oracleUsdxToUsd(usdxAmount); sweepAmount = sweep.convertToSWEEP(usdxInUsd); uint256 sweepBalance = sweep.balanceOf(address(this)); if (sweepAmount > sweepBalance) revert NotEnoughBalance(); TransferHelper.safeTransferFrom( address(usdx), msg.sender, address(this), usdxAmount ); TransferHelper.safeTransfer(address(sweep), msg.sender, sweepAmount); emit BoughtSWEEP(sweepAmount); } /** * @notice Sell Sweep with Stabilizer * Sells sweep amount to the stabilizer (swaps SWEEP to USDX). * @param sweepAmount. * @dev Decreases the sweep balance and increase usdx balance */ function swapSweepToUsdx(uint256 sweepAmount) public onlyBorrower whenNotPaused validAmount(sweepAmount) nonReentrant returns (uint256 usdxAmount) { uint256 sweepInUsd = sweep.convertToUSD(sweepAmount); usdxAmount = _oracleUsdToUsdx(sweepInUsd); uint256 usdxBalance = usdx.balanceOf(address(this)); if (usdxAmount > usdxBalance) revert NotEnoughBalance(); TransferHelper.safeTransferFrom(address(sweep), msg.sender, address(this), sweepAmount); TransferHelper.safeTransfer(address(usdx), msg.sender, usdxAmount); emit SoldSWEEP(usdxAmount); } function oneStepInvest(uint256 sweepAmount, uint256 slippage, bool useAMM) external onlyBorrower whenNotPaused validAmount(sweepAmount) nonReentrant returns(uint256 usdxAmount) { _borrow(sweepAmount); if(useAMM){ usdxAmount = _sell(sweepAmount, slippage); } else { usdxAmount = swapSweepToUsdx(sweepAmount); } _invest(usdxAmount, 0, slippage); if (getEquityRatio() < minEquityRatio){ revert EquityRatioExcessed(); } } function oneStepDivest(uint256 usdxAmount, uint256 slippage, bool useAMM) external onlyBorrower whenNotPaused validAmount(usdxAmount) nonReentrant returns(uint256 sweepAmount) { _divest(usdxAmount, slippage); if(useAMM){ sweepAmount = _buy(usdxAmount, slippage); } else { sweepAmount = swapUsdxToSweep(usdxAmount); } _repay(sweepAmount); } /** * @notice Withdraw SWEEP * Takes out sweep balance if the new equity ratio is higher than the minimum equity ratio. * @param token. * @param amount. * @dev Decreases the sweep balance. */ function withdraw(address token, uint256 amount) external onlyBorrower whenNotPaused validAmount(amount) nonReentrant { uint256 balance = IERC20Metadata(token).balanceOf(address(this)); if (amount > balance) amount = balance; TransferHelper.safeTransfer(token, msg.sender, amount); if (sweepBorrowed > 0 && getEquityRatio() < minEquityRatio) { revert EquityRatioExcessed(); } emit Withdrawn(token, amount); } /** * @notice Start auction * Initiates a dutch auction for liquidation. */ function startAuction() external nonReentrant { if (!isDefaulted()) revert NotDefaulted(); if(!auctionAllowed || startingPrice > 0) revert ActionNotAllowed(); startingTime = block.timestamp; uint256 minEquity = (PRECISION - uint256(minEquityRatio)); startingPrice = getDebt() * PRECISION / minEquity; } /** * @notice Buy auction * Allows a user to participate in the auction by buying assets */ function buyAuction() external nonReentrant { if(startingTime == 0) revert AuctionNotActive(); uint256 debt = getAuctionAmount(); address token = _getToken(); _liquidate(token, debt); } /* ========== Internals ========== */ function assetValue() public view virtual returns (uint256) { return 0; } /** * @notice Invest To Asset. */ function _invest(uint256, uint256, uint256) internal virtual {} /** * @notice Divest From Asset. */ function _divest(uint256, uint256) internal virtual {} /** * @notice Get asset address to liquidate. */ function _getToken() internal view virtual returns (address) {} /** * @notice Stop the auction. */ function _stopAuction() internal { startingTime = 0; startingPrice = 0; } /** * @notice Liquidates * A liquidator repays the debt in sweep and gets the same value * of the assets that the stabilizer holds at a discount */ function _liquidate( address token, uint256 debt ) internal { if (!isDefaulted()) revert NotDefaulted(); address self = address(this); uint256 usdxBalance = usdx.balanceOf(self); uint256 tokenBalance = IERC20Metadata(token).balanceOf(self); uint256 sweepBalance = sweep.balanceOf(self); if(debt > sweepBalance) { // Takes SWEEP from the liquidator and repays debt TransferHelper.safeTransferFrom( address(sweep), msg.sender, self, debt - sweepBalance ); } // Gives all the assets to the liquidator TransferHelper.safeTransfer(address(usdx), msg.sender, usdxBalance); TransferHelper.safeTransfer(token, msg.sender, tokenBalance); _repay(debt); emit Liquidated(msg.sender); } function _buy( uint256 usdxAmount, uint256 slippage ) internal returns (uint256 sweepAmount) { uint256 usdxBalance = usdx.balanceOf(address(this)); usdxAmount = usdxAmount.min(usdxBalance); if (usdxAmount == 0) revert NotEnoughBalance(); sweepAmount = sweep.convertToSWEEP(_oracleUsdxToUsd(usdxAmount)); uint256 minAmountOut = OvnMath.subBasisPoints(sweepAmount, slippage); IAMM _amm = amm(); TransferHelper.safeApprove(address(usdx), address(_amm), usdxAmount); sweepAmount = _amm.buySweep( address(usdx), usdxAmount, minAmountOut ); return sweepAmount; } function _sell( uint256 sweepAmount, uint256 slippage ) internal returns (uint256 usdxAmount) { uint256 sweepBalance = sweep.balanceOf(address(this)); sweepAmount = sweepAmount.min(sweepBalance); if (sweepAmount == 0) revert NotEnoughBalance(); usdxAmount = _oracleUsdToUsdx(sweep.convertToUSD(sweepAmount)); uint256 minAmountOut = OvnMath.subBasisPoints(usdxAmount, slippage); IAMM _amm = amm(); TransferHelper.safeApprove(address(sweep), address(_amm), sweepAmount); usdxAmount = _amm.sellSweep( address(usdx), sweepAmount, minAmountOut ); return usdxAmount; } function _borrow(uint256 sweepAmount) internal { if (!sweep.isValidMinter(address(this))) revert InvalidMinter(); uint256 sweepAvailable = loanLimit - sweepBorrowed; if (sweepAvailable < sweepAmount) revert NotEnoughBalance(); uint256 spreadAmount = accruedFee(); sweep.mint(sweepAmount); sweepBorrowed += sweepAmount; spreadDate = block.timestamp; if (spreadAmount > 0) { TransferHelper.safeTransfer( address(sweep), sweep.treasury(), spreadAmount ); emit PayFee(spreadAmount); } emit Borrowed(sweepAmount); } function _repay(uint256 sweepAmount) internal { uint256 sweepBalance = sweep.balanceOf(address(this)); sweepAmount = sweepAmount.min(sweepBalance); if (sweepAmount == 0) revert NotEnoughBalance(); callAmount = (callAmount > sweepAmount) ? (callAmount - sweepAmount) : 0; if (callDelay > 0 && callAmount == 0) callTime = 0; uint256 spreadAmount = accruedFee(); spreadDate = block.timestamp; sweepAmount = sweepAmount - spreadAmount; if (sweepBorrowed < sweepAmount) { sweepAmount = sweepBorrowed; sweepBorrowed = 0; } else { sweepBorrowed -= sweepAmount; } TransferHelper.safeTransfer( address(sweep), sweep.treasury(), spreadAmount ); TransferHelper.safeApprove(address(sweep), address(this), sweepAmount); sweep.burn(sweepAmount); emit Repaid(sweepAmount); if(!isDefaulted()) _stopAuction(); } /** * @notice Get Balances of the usdx and SWEEP. **/ function _balances() internal view returns (uint256 usdxBalance, uint256 sweepBalance) { usdxBalance = usdx.balanceOf(address(this)); sweepBalance = sweep.balanceOf(address(this)); } function _onlyBorrower() internal view { if (msg.sender != borrower) revert NotBorrower(); } function _onlySettingsEnabled() internal view { if (!settingsEnabled) revert SettingsDisabled(); } function _validAmount(uint256 amount) internal pure { if (amount == 0) revert OverZero(); } function _oracleUsdxToUsd( uint256 usdxAmount ) internal view returns (uint256) { return ChainlinkLibrary.convertTokenToUsd( usdxAmount, usdx.decimals(), oracleUsdx ); } function _oracleUsdToUsdx( uint256 usdAmount ) internal view returns (uint256) { return ChainlinkLibrary.convertUsdToToken( usdAmount, usdx.decimals(), oracleUsdx ); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; interface ISweep { struct Minter { uint256 maxAmount; uint256 mintedAmount; bool isListed; bool isEnabled; } function isMintingAllowed() external view returns (bool); function DEFAULT_ADMIN_ADDRESS() external view returns (address); function balancer() external view returns (address); function treasury() external view returns (address); function allowance( address holder, address spender ) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function balanceOf(address account) external view returns (uint256); function decimals() external view returns (uint8); function decreaseAllowance( address spender, uint256 subtractedValue ) external returns (bool); function isValidMinter(address) external view returns (bool); function amm() external view returns (address); function ammPrice() external view returns (uint256); function twaPrice() external view returns (uint256); function increaseAllowance( address spender, uint256 addedValue ) external returns (bool); function name() external view returns (string memory); function owner() external view returns (address); function fastMultisig() external view returns (address); function burn(uint256 amount) external; function mint(uint256 amount) external; function minters(address minterAaddress) external returns (Minter memory); function minterAddresses(uint256 index) external view returns (address); function getMinters() external view returns (address[] memory); function targetPrice() external view returns (uint256); function interestRate() external view returns (int256); function periodStart() external view returns (uint256); function stepValue() external view returns (int256); function arbSpread() external view returns (uint256); function refreshInterestRate(int256 newInterestRate, uint256 newPeriodStart) external; function setTargetPrice( uint256 currentTargetPrice, uint256 nextTargetPrice ) external; function setInterestRate( int256 currentInterestRate, int256 nextInterestRate ) external; function setPeriodStart( uint256 currentPeriodStart, uint256 nextPeriodStart ) external; function startNewPeriod() external; function symbol() external view returns (string memory); function totalSupply() external view returns (uint256); function convertToUSD(uint256 amount) external view returns (uint256); function convertToSWEEP(uint256 amount) external view returns (uint256); function transfer( address recipient, uint256 amount ) external returns (bool); function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_sweep","type":"address"},{"internalType":"address","name":"_usdx","type":"address"},{"internalType":"address","name":"_oracleUsdx","type":"address"},{"internalType":"address","name":"_poolAddress","type":"address"},{"internalType":"address","name":"_borrower","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ActionNotAllowed","type":"error"},{"inputs":[],"name":"AssetDefaulted","type":"error"},{"inputs":[],"name":"AuctionNotActive","type":"error"},{"inputs":[],"name":"BadAddress","type":"error"},{"inputs":[],"name":"BadSlippage","type":"error"},{"inputs":[],"name":"EquityRatioExcessed","type":"error"},{"inputs":[],"name":"InvalidMinter","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"NotAutoInvest","type":"error"},{"inputs":[],"name":"NotAutoInvestMinAmount","type":"error"},{"inputs":[],"name":"NotAutoInvestMinRatio","type":"error"},{"inputs":[],"name":"NotBalancer","type":"error"},{"inputs":[],"name":"NotBorrower","type":"error"},{"inputs":[],"name":"NotDefaulted","type":"error"},{"inputs":[],"name":"NotEnoughBalance","type":"error"},{"inputs":[],"name":"NotGovernance","type":"error"},{"inputs":[],"name":"NotMultisigOrGov","type":"error"},{"inputs":[],"name":"NotSweep","type":"error"},{"inputs":[],"name":"OverZero","type":"error"},{"inputs":[],"name":"SettingsDisabled","type":"error"},{"inputs":[],"name":"SpreadNotEnough","type":"error"},{"inputs":[],"name":"ZeroAddressDetected","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"AutoCalled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"AutoInvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"Borrowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"Bought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"BoughtSWEEP","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"CallCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"int256","name":"minEquityRatio","type":"int256"},{"indexed":true,"internalType":"uint256","name":"spreadFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loanLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"decreaseFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"callDelay","type":"uint256"},{"indexed":false,"internalType":"int256","name":"autoInvestMinRatio","type":"int256"},{"indexed":false,"internalType":"uint256","name":"autoInvestMinAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minLiquidationRatio","type":"uint256"},{"indexed":false,"internalType":"bool","name":"autoInvestEnabled","type":"bool"},{"indexed":false,"internalType":"bool","name":"_auctionAllowed","type":"bool"},{"indexed":false,"internalType":"string","name":"url","type":"string"}],"name":"ConfigurationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Liquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"usdxAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"LiquidityAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"usdxAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"LiquidityRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"loanLimit","type":"uint256"}],"name":"LoanLimitChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"PayFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrower","type":"address"}],"name":"Proposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrower","type":"address"}],"name":"Rejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"Repaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"Sold","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"usdxAmount","type":"uint256"}],"name":"SoldSWEEP","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"SweepBorrowedChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"sweeAmount","type":"uint256"}],"name":"SweepPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"accruedFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"},{"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"addLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"amm","outputs":[{"internalType":"contract IAMM","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"sweepAmount","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"autoCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"sweepAmount","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"autoInvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"autoInvestEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"autoInvestMinAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"autoInvestMinRatio","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"borrower","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bptIndex","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"}],"name":"buySweep","outputs":[{"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"buySweepOnAMM","outputs":[{"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"callAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"_minEquityRatio","type":"int256"},{"internalType":"uint256","name":"_spreadFee","type":"uint256"},{"internalType":"uint256","name":"_loanLimit","type":"uint256"},{"internalType":"uint256","name":"_decreaseFactor","type":"uint256"},{"internalType":"uint256","name":"_callDelay","type":"uint256"},{"internalType":"int256","name":"_autoInvestMinRatio","type":"int256"},{"internalType":"uint256","name":"_autoInvestMinAmount","type":"uint256"},{"internalType":"uint256","name":"_minLiquidationRatio","type":"uint256"},{"internalType":"bool","name":"_autoInvestEnabled","type":"bool"},{"internalType":"bool","name":"_auctionAllowed","type":"bool"},{"internalType":"string","name":"_url","type":"string"}],"name":"configure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decreaseFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAuctionAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBuyPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEquityRatio","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getJuniorTrancheValue","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"},{"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"initPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isDefaulted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"link","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"loanLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minEquityRatio","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minLiquidationRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"},{"internalType":"uint256","name":"slippage","type":"uint256"},{"internalType":"bool","name":"useAMM","type":"bool"}],"name":"oneStepDivest","outputs":[{"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"sweepAmount","type":"uint256"},{"internalType":"uint256","name":"slippage","type":"uint256"},{"internalType":"bool","name":"useAMM","type":"bool"}],"name":"oneStepInvest","outputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracleUsdx","outputs":[{"internalType":"contract IPriceFeed","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract IBalancerPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolAssets","outputs":[{"internalType":"contract IAsset","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"propose","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reject","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"},{"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"removeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"sweepAmount","type":"uint256"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"sellSweepOnAMM","outputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newLoanLimit","type":"uint256"}],"name":"setLoanLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newSlippage","type":"uint32"}],"name":"setSlippage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settingsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"slippage","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"spreadDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"spreadFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startingPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startingTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"name":"swapSweepToUsdx","outputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"}],"name":"swapUsdxToSweep","outputs":[{"internalType":"uint256","name":"sweepAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sweep","outputs":[{"internalType":"contract ISweep","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sweepBorrowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sweepIndex","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"updateSweepBorrowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdx","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdxIndex","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IBalancerVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162006128380380620061288339810160408190526200003491620005db565b8585858584836001600160a01b0381166200006257604051632887dd7560e11b815260040160405180910390fd5b6001600160a01b039081166080526000805460ff191690556001805581166200009e57604051632887dd7560e11b815260040160405180910390fd5b6004620000ac86826200077c565b50600280546001600160a01b03199081166001600160a01b039586161790915560038054821693851693909317909255600580549092169083161790556011805461010061ff00199091168117909155601a805466ffffffff000000191664138800000017905560168054610100600160a81b03191687841683021790819055604080516311b2515f60e31b81529051929091049092169350638d928af8925060048281019260209291908290030181865afa15801562000171573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000197919062000848565b601780546001600160a01b0319166001600160a01b039283161790556016546040805163038fff2d60e41b81529051610100909204909216916338fff2d09160048083019260209291908290030181865afa158015620001fb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022191906200086f565b6018819055601754604051631f29a8cd60e31b815260048101929092526001600160a01b03169063f94d466890602401600060405180830381865afa1580156200026f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000299919081019062000922565b50508051620002b0906019906020840190620004e6565b50506200031d60805160198054806020026020016040519081016040528092919081815260200182805480156200031157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311620002f2575b50506200045f92505050565b601a805460ff191660ff929092169190911790556002546019805460408051602080840282018101909252828152620003a3946001600160a01b0316939092909183018282801562000311576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311620002f25750506200045f92505050565b601a60016101000a81548160ff021916908360ff16021790555062000439601660019054906101000a90046001600160a01b0316601980548060200260200160405190810160405280929190818152602001828054801562000311576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311620002f25750506200045f92505050565b601a60026101000a81548160ff021916908360ff16021790555050505050505062000a41565b6000805b82518160ff161015620004c657836001600160a01b0316838260ff1681518110620004925762000492620009fd565b60200260200101516001600160a01b031603620004b1579050620004e0565b80620004bd8162000a13565b91505062000463565b506040516332691b5760e01b815260040160405180910390fd5b92915050565b8280548282559060005260206000209081019282156200053e579160200282015b828111156200053e57825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019062000507565b506200054c92915062000550565b5090565b5b808211156200054c576000815560010162000551565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620005a857620005a862000567565b604052919050565b6001600160a01b0381168114620005c657600080fd5b50565b8051620005d681620005b0565b919050565b60008060008060008060c08789031215620005f557600080fd5b86516001600160401b03808211156200060d57600080fd5b818901915089601f8301126200062257600080fd5b81518181111562000637576200063762000567565b602091506200064f601f8201601f191683016200057d565b8181528b838386010111156200066457600080fd5b60005b828110156200068457848101840151828201850152830162000667565b50600083838301015280995050506200069f818a01620005c9565b96505050620006b160408801620005c9565b9350620006c160608801620005c9565b9250620006d160808801620005c9565b9150620006e160a08801620005c9565b90509295509295509295565b600181811c908216806200070257607f821691505b6020821081036200072357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200077757600081815260208120601f850160051c81016020861015620007525750805b601f850160051c820191505b8181101562000773578281556001016200075e565b5050505b505050565b81516001600160401b0381111562000798576200079862000567565b620007b081620007a98454620006ed565b8462000729565b602080601f831160018114620007e85760008415620007cf5750858301515b600019600386901b1c1916600185901b17855562000773565b600085815260208120601f198616915b828110156200081957888601518255948401946001909101908401620007f8565b5085821015620008385787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156200085b57600080fd5b81516200086881620005b0565b9392505050565b6000602082840312156200088257600080fd5b5051919050565b60006001600160401b03821115620008a557620008a562000567565b5060051b60200190565b600082601f830112620008c157600080fd5b81516020620008da620008d48362000889565b6200057d565b82815260059290921b84018101918181019086841115620008fa57600080fd5b8286015b84811015620009175780518352918301918301620008fe565b509695505050505050565b6000806000606084860312156200093857600080fd5b83516001600160401b03808211156200095057600080fd5b818601915086601f8301126200096557600080fd5b8151602062000978620008d48362000889565b82815260059290921b8401810191818101908a8411156200099857600080fd5b948201945b83861015620009c3578551620009b381620005b0565b825294820194908201906200099d565b91890151919750909350505080821115620009dd57600080fd5b50620009ec86828701620008af565b925050604084015190509250925092565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff810362000a3857634e487b7160e01b600052601160045260246000fd5b60010192915050565b60805161554a62000bde6000396000818161058801528181610830015281816108be01528181610b2801528181610bbe01528181610c6901528181610cf601528181610e4001528181610ee001528181610f0101528181610fcb01528181611040015281816110c2015281816111d50152818161127301528181611331015281816114bf0152818161153d0152818161161a015281816116e6015281816117f80152818161190001528181611a7401528181611b1201528181611be501528181611c8301528181611e1801528181611ebd01528181612261015281816122920152818161232a0152818161289a015281816129c701528181612af101528181612cae0152818161303c01528181613154015281816132cd015281816133b50152818161343f015281816134600152818161356401528181613618015281816136b101528181613a1001528181613b4201528181613b6301528181613bc401528181613c0001528181613d9e01528181613f3001528181613fe90152818161423b015281816142e00152818161473401526147ae015261554a6000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80636b64c76911610220578063ba2d034411610130578063de839ba4116100b8578063f686138d11610087578063f686138d146107dc578063f69aa3d5146107e5578063f95c1b26146107f8578063fa45d56214610805578063fbfa77cf1461081857600080fd5b8063de839ba41461079a578063ea8364aa146107a3578063f2674f22146107b6578063f3fef3a3146107c957600080fd5b8063c198f8ba116100ff578063c198f8ba14610765578063c5ebeaec1461076d578063c6beb58614610780578063d366a41f14610789578063d6fbf2021461079157600080fd5b8063ba2d03441461072f578063bb35212014610737578063bc5477ad14610740578063c0f4a0051461075357600080fd5b80639d7de6b3116101b3578063a516ed0211610182578063a516ed02146106fb578063a6a8f1f914610703578063a71891c31461070c578063ad81fced14610714578063b220a79b1461071d57600080fd5b80639d7de6b3146106c45780639e1b0045146106d7578063a1951665146106ea578063a38aaa90146106f357600080fd5b80638351faf5116101ef5780638351faf5146106835780638456cb59146106965780638d1d7c611461069e5780639cd441da146106b157600080fd5b80636b64c7691461064d578063717e794d146106555780637df1f1b91461065d57806381680d0a1461067057600080fd5b806329b154c31161031b5780633e032a3b116102ae5780634dc415de1161027d5780634dc415de1461060c5780635c975abb1461061457806361ab077f1461061f578063698996f81461063257806369ae990b1461063a57600080fd5b80633e032a3b146105c65780633e0dc34e146105f25780633f4ba83a146105fb57806348dcacab1461060357600080fd5b80633168b03f116102ea5780633168b03f1461057057806335faa41614610583578063371fd8e6146105aa57806339518b5e146105bd57600080fd5b806329b154c3146105395780632a9439451461054c5780632d76643c14610554578063311176d71461055d57600080fd5b80631370720f1161039e5780631de01bc91161036d5780631de01bc9146104ee57806323443944146104f757806325d9b7921461050157806329610252146105145780632982db001461051c57600080fd5b80631370720f1461049b57806314a6bf0f146104ae57806316f0115b146104b65780631c4695f4146104e657600080fd5b80630e5f5dbd116103da5780630e5f5dbd146104745780630f5e07c71461047c57806312bec0021461048557806312f21a1a1461049257600080fd5b8063018a25e81461040c57806306fdde0314610427578063095559aa1461043c5780630a2468711461044f575b600080fd5b61041461082b565b6040519081526020015b60405180910390f35b61042f610962565b60405161041e9190614bf2565b61041461044a366004614c13565b6109f0565b601a546104629062010000900460ff1681565b60405160ff909116815260200161041e565b610414610a7b565b61041460095481565b601a546104629060ff1681565b610414600d5481565b6104146104a9366004614c4c565b610ae0565b610414610ccb565b6016546104ce9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161041e565b61042f610ce7565b610414600a5481565b6104ff610cf4565b005b6104ce61050f366004614c4c565b610ddd565b6104ff610e07565b6016546105299060ff1681565b604051901515815260200161041e565b6104ff610547366004614c4c565b610fc0565b6104ce61103c565b61041460075481565b6002546104ce906001600160a01b031681565b6104ff61057e366004614c4c565b6110c0565b6104ce7f000000000000000000000000000000000000000000000000000000000000000081565b6104ff6105b8366004614c4c565b6111ae565b61041460125481565b601a546105dd906301000000900463ffffffff1681565b60405163ffffffff909116815260200161041e565b61041460185481565b6104ff6111d3565b610414600b5481565b6104ff61132f565b60005460ff16610529565b61041461062d366004614c65565b61142b565b61041461148c565b610414610648366004614c4c565b611606565b6104ff61174d565b6104146117f3565b6005546104ce906001600160a01b031681565b61041461067e366004614c13565b6118a6565b6104ff610691366004614c87565b6118f6565b6104ff611a72565b6003546104ce906001600160a01b031681565b6104ff6106bf366004614c65565b611bce565b6104ff6106d2366004614c65565b611cfb565b6104ff6106e5366004614c65565b612211565b61041460105481565b610529612516565b6104ff61255c565b61041460155481565b61041461259f565b61041460085481565b601a5461046290610100900460ff1681565b6104146127d3565b61041460145481565b6104ff61074e366004614c87565b612890565b60115461052990610100900460ff1681565b6104ff612bb6565b6104ff61077b366004614c4c565b612c03565b61041460065481565b610414612c61565b61041460135481565b610414600c5481565b6104ff6107b1366004614cfc565b612d68565b6104ff6107c4366004614dc3565b612e27565b6104ff6107d7366004614dfe565b612e86565b610414600f5481565b6104146107f3366004614c65565b612fa4565b6011546105299060ff1681565b610414610813366004614c4c565b612fff565b6017546104ce906001600160a01b031681565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663dc38679c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b09190614e2a565b9050620f424062ffffff16817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e19538476040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093e9190614e2a565b6109489190614e59565b6109529190614e86565b61095c9082614e9a565b91505090565b6004805461096f90614ead565b80601f016020809104026020016040519081016040528092919081815260200182805461099b90614ead565b80156109e85780601f106109bd576101008083540402835291602001916109e8565b820191906000526020600020905b8154815290600101906020018083116109cb57829003601f168201915b505050505081565b60006109fa6131c8565b610a026131f3565b83610a0c8161323e565b610a1461325f565b610a1d856132b8565b8215610a3457610a2d8585613542565b9150610a40565b610a3d85612fff565b91505b600654610a4b612c61565b1215610a6a5760405163374c72ff60e11b815260040160405180910390fd5b610a7360018055565b509392505050565b60075460009015610ada57600062015180600d5442610a9a9190614ee1565b610aa49190614e86565b9050610ab5620f424061016d614e59565b81600c54600754610ac69190614e59565b610ad09190614e59565b61095c9190614e86565b50600090565b6000610aea6131c8565b610af26131f3565b81610afc8161323e565b610b0461325f565b6000610b0f84613760565b604051633068b6b560e21b8152600481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c1a2dad490602401602060405180830381865afa158015610b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9b9190614e2a565b6040516370a0823160e01b81523060048201529093506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c299190614e2a565b905080841115610c4c5760405163569d45cf60e11b815260040160405180910390fd5b600254610c64906001600160a01b03163330886137ee565b610c8f7f000000000000000000000000000000000000000000000000000000000000000033866138f8565b60405184907fbc87b68cd9f40bbab98db9b9e4d393c4ef32d4660271a908b81cfa10d8a59df990600090a25050610cc560018055565b50919050565b6000610cd5610a7b565b600754610ce29190614e9a565b905090565b600e805461096f90614ead565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d769190614ef4565b6001600160a01b0316336001600160a01b031614610da75760405163698bba4b60e01b815260040160405180910390fd5b6000600b81905560098190556040517f219124ae95cc25cf220d998f2867d37fb4ab4908cce7c51adfa33ce747aa5747908290a2565b60198181548110610ded57600080fd5b6000918252602090912001546001600160a01b0316905081565b610e0f6131c8565b610e1761325f565b6000610e21610a7b565b42600d556040516370a0823160e01b81523060048201529091506000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610e8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb39190614e2a565b905080821115610ed5576040516206230160eb1b815260040160405180910390fd5b8115610fb357610f877f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166361d027b36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f819190614ef4565b846138f8565b60405182907fda0ff68ccd5fb797a8f86207386ea961ca6990c15ace2424ab51eb871ed4959990600090a25b5050610fbe60018055565b565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146110095760405163bc9eca6160e01b815260040160405180910390fd5b600781905560405181907f35ba42ee3c2daa6cf14836eefff16b184565798767ec1e5d723008848aeaf7e390600090a250565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632a9439456040518163ffffffff1660e01b8152600401602060405180830381865afa15801561109c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce29190614ef4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561111e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111429190614ef4565b6001600160a01b0316336001600160a01b0316146111735760405163698bba4b60e01b815260040160405180910390fd5b60088190556040518181527f7760d892a7883522367f0eaea35e968381a018418c249cd9aaaca190fe5d88179060200160405180910390a150565b6111b66131c8565b6111be61325f565b6111c7816139f8565b6111d060018055565b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663baf4a3126040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190614ef4565b6001600160a01b0316336001600160a01b03161415801561130957507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f39190614ef4565b6001600160a01b0316336001600160a01b031614155b1561132757604051631e1c735b60e21b815260040160405180910390fd5b610fbe613caa565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561138d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b19190614ef4565b6001600160a01b0316336001600160a01b0316146113e257604051632d5be4cb60e21b815260040160405180910390fd5b6011805461ff0019166101001790556005546040516001600160a01b03909116907faf77f8960cf590e245ec8b6d41c193a5dcacad8986ae4eb57ac9e5be7b6af03190600090a2565b60006114356131c8565b61143d6131f3565b61144561325f565b61144f8383613cfc565b60405190915081907f4e08ba899977cf7d4c2964bce71c6b9a7ef76ee5166a4c1249a1e08016e33ef190600090a261148660018055565b92915050565b6000806000611499613ea7565b60405163113b4fbf60e31b81526004810182905291935091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906389da7df890602401602060405180830381865afa158015611506573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152a9190614e2a565b9050600061153784613760565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389da7df8611572610a7b565b6040518263ffffffff1660e01b815260040161159091815260200190565b602060405180830381865afa1580156115ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d19190614e2a565b90508083836115de61259f565b6115e89190614e9a565b6115f29190614e9a565b6115fc9190614ee1565b9550505050505090565b600061161061325f565b61161861082b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169a9190614f11565b6116a590600a615018565b6116ae84613760565b6116b89190614e59565b6116c29190614e86565b90506116d76116d2826002614e59565b6132b8565b6116e18282613fa9565b61170c7f000000000000000000000000000000000000000000000000000000000000000033836138f8565b6040518281527f6e19477745f02fa64cb79e709afd8b6a5da159ef7b135546eafd67c38e425c439060200160405180910390a161174860018055565b919050565b61175561325f565b61175d612516565b61177a5760405163038cbd4b60e31b815260040160405180910390fd5b60165460ff16158061178e57506000601354115b156117ac5760405163829e373360e01b815260040160405180910390fd5b426012556006546000906117c390620f4240614ee1565b905080620f42406117d2610ccb565b6117dc9190614e59565b6117e69190614e86565b60135550610fbe60018055565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389da7df86007546040518263ffffffff1660e01b815260040161184691815260200190565b602060405180830381865afa158015611863573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118879190614e2a565b9050600061189361148c565b905061189f8282615027565b9250505090565b60006118b06131c8565b6118b86131f3565b836118c28161323e565b6118ca61325f565b82156118e1576118da8585613cfc565b91506118ed565b6118ea85610ae0565b91505b610a6a826139f8565b6118fe61325f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190614ef4565b6001600160a01b0316336001600160a01b0316146119b15760405163698bba4b60e01b815260040160405180910390fd5b60115460ff166119d4576040516305b02a1960e01b815260040160405180910390fd5b6010548310156119f7576040516312cd610d60e21b815260040160405180910390fd5b611a00836132b8565b6000611a0c8483613542565b9050600f54611a19612c61565b1215611a38576040516378764b0f60e01b815260040160405180910390fd5b60405184907f8f77e6a87a8210bff9857b08990b1f360b73d6e92d422a9a0e2c78e449682a9c90600090a250611a6d60018055565b505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663baf4a3126040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ad0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af49190614ef4565b6001600160a01b0316336001600160a01b031614158015611ba857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b929190614ef4565b6001600160a01b0316336001600160a01b031614155b15611bc657604051631e1c735b60e21b815260040160405180910390fd5b610fbe6144d2565b611bd661325f565b611bde6131c8565b60003090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632b4818836040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c65919061504e565b15611c7e578115611c7957611c79826132b8565b611caa565b611caa7f00000000000000000000000000000000000000000000000000000000000000003383856137ee565b611cb48383613fa9565b60408051848152602081018490527f38f8a0c92f4c5b0b6877f878cb4c0c8d348a47b76d716c8e78f425043df9515b910160405180910390a150611cf760018055565b5050565b611d0361325f565b611d0b6131c8565b6002546040805163313ce56760e01b8152905130926000926001600160a01b039091169163313ce567916004808201926020929091908290030181865afa158015611d5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7e9190614f11565b611d8990600a615018565b601654600254604051632a6f500560e11b81526001600160a01b03918216600482015261010090920416906354dea00a90602401602060405180830381865afa158015611dda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfe9190614e2a565b611e089086614e59565b611e129190614e86565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e989190614f11565b611ea390600a615018565b601654604051632a6f500560e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152610100909204909116906354dea00a90602401602060405180830381865afa158015611f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f379190614e2a565b611f419086614e59565b611f4b9190614e86565b601a54909150600090620f424090611f70906301000000900463ffffffff168261506b565b63ffffffff16611f808486614e9a565b611f8a9190614e59565b611f949190614e86565b60408051600380825260808201909252919250600091906020820160608036833701905050601a54815191925088918391610100900460ff16908110611fdc57611fdc61509e565b6020908102919091010152601a5481518791839160ff9091169081106120045761200461509e565b60209081029190910101526040805160028082526060820190925260009181602001602082028036833701905050601a5490915060ff6101008204811691161161204e5786612050565b875b816000815181106120635761206361509e565b6020908102919091010152601a5460ff610100820481169116116120875787612089565b865b8160018151811061209c5761209c61509e565b6020026020010181815250506000600182856040516020016120c093929190615105565b60408051601f198184030181526019805460a060208202860181019094526080850181815292955060009493849392919084018282801561212a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161210c575b505050918352505060208101869052604080820185905260006060909201919091526017546018549151638bdb391360e01b81529293506001600160a01b031691638bdb391391612183918c90819087906004016151cd565b600060405180830381600087803b15801561219d57600080fd5b505af11580156121b1573d6000803e3d6000fd5b5050505060008911156121c7576121c7896139f8565b604080518b8152602081018b90527f6f0f96292ae0038c04f9b6bab30f185d9ca02c471d0983f563f2a4f674aef137910160405180910390a15050505050505050611cf760018055565b61221961325f565b6122216131c8565b600254309061223b906001600160a01b03163383866137ee565b600254601754612258916001600160a01b0390811691168561450f565b601754612290907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03168461450f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632b4818836040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612312919061504e565b1561232557612320826132b8565b612351565b6123517f00000000000000000000000000000000000000000000000000000000000000003383856137ee565b604080516003808252608082019092526000916020820160608036833701905050601a548151919250600160701b91839162010000900460ff1690811061239a5761239a61509e565b6020026020010181815250508381601a60019054906101000a900460ff1660ff16815181106123cb576123cb61509e565b6020908102919091010152601a5481518491839160ff9091169081106123f3576123f361509e565b60200260200101818152505060008082604051602001612414929190615213565b60408051601f198184030181526019805460a060208202860181019094526080850181815292955060009493849392919084018282801561247e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612460575b50505091835250506020810185905260408082018590526000606090920191909152601754601854915163172b958560e31b81529293506001600160a01b03169163b95cac28916124d7918890819087906004016151cd565b600060405180830381600087803b1580156124f157600080fd5b505af1158015612505573d6000803e3d6000fd5b5050505050505050611cf760018055565b600080600a5411801561252b57506000600b54115b8015612538575060095442115b80610ce257506000600754118015610ce25750600654612556612c61565b12905090565b61256461325f565b601254600003612587576040516334dc687f60e11b815260040160405180910390fd5b60006125916127d3565b90506000610fb38183614608565b6016546040516370a0823160e01b815230600482015260009182916101009091046001600160a01b0316906370a0823190602401602060405180830381865afa1580156125f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126149190614e2a565b90506000601660019054906101000a90046001600160a01b03166001600160a01b031663679aefce6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561266b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268f9190614e2a565b90506000601660019054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270a9190614f11565b61271590600261523b565b61272090600a615018565b600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612773573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127979190614f11565b6127a290600a615018565b6127ac8486614e59565b6127b69190614e59565b6127c09190614e86565b90506127cb81613760565b935050505090565b600080620f4240601554620f42406127eb9190614ee1565b6007546127f89190614e59565b6128029190614e86565b9050600061012c601254426128179190614ee1565b6128219190614e86565b90506000601454826128339190614e59565b9050620f424081111561284857509092915050565b600061285782620f4240614ee1565b90506000620f42408260135461286d9190614e59565b6128779190614e86565b905080851161288657806115fc565b5092949350505050565b61289861325f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061291a9190614ef4565b6001600160a01b0316336001600160a01b03161461294b5760405163698bba4b60e01b815260040160405180910390fd5b600080612956613ea7565b91509150600061296e612967610ccb565b879061483c565b600a549091501561298f57600a546129869042614e9a565b600955600b8190555b80821015612ad95760006129a38383614ee1565b60405163113b4fbf60e31b8152600481018290529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906389da7df890602401602060405180830381865afa158015612a0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a329190614e2a565b90506000612a3f82614852565b905085811115612a5657612a566111d08783614ee1565b6002546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac39190614e2a565b1115612ad557612ad38188613cfc565b505b5050505b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b649190614e2a565b118015612b715750600081115b15612b7f57612b7f816139f8565b60405186907fdfcd68ceed46252749a4089f344aec4b4ee7f28a068f704c21799355325f3da990600090a2505050611a6d60018055565b612bbe6131c8565b6011805461ff00191690556005546040516001600160a01b03909116907facf29ad8d63913d38e7e1176963a4afb76bf0918516051da68408ecb6f98065d90600090a2565b612c0b6131c8565b612c136131f3565b80612c1d8161323e565b612c2561325f565b612c2e826132b8565b600654612c39612c61565b1215612c585760405163374c72ff60e11b815260040160405180910390fd5b611cf760018055565b600080612c6c61148c565b905080600003612c915760075415612c8957620f423f1991505090565b600091505090565b60075460405163113b4fbf60e31b81526000916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916389da7df891612ce59160040190815260200190565b602060405180830381865afa158015612d02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d269190614e2a565b9050600082612d358382615027565b612d4290620f4240615257565b612d4c9190615287565b9050620f423f19811215612d615750620f423f195b9392505050565b612d706131c8565b612d786148e7565b60068c9055600c8b905560088a90556014899055600a889055600f879055601086905560158590556011805460ff199081168615151790915560168054909116841515179055600e612dcb8284836152fb565b508a8c7fed1352796b02006c8bf7ef68956cb9fc55c08f9193eee9cec7ee590840bbbaad8c6014548c8c8c8c8c8c8c8c604051612e119a999897969594939291906153bb565b60405180910390a3505050505050505050505050565b612e2f61325f565b612e376131c8565b620f424063ffffffff82161115612e6157604051630f4ec00b60e01b815260040160405180910390fd5b601a805466ffffffff0000001916630100000063ffffffff8416021790556001805550565b612e8e6131c8565b612e966131f3565b80612ea08161323e565b612ea861325f565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015612eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f139190614e2a565b905080831115612f21578092505b612f2c8433856138f8565b6000600754118015612f465750600654612f44612c61565b125b15612f645760405163374c72ff60e11b815260040160405180910390fd5b60405183906001600160a01b038616907f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d590600090a350611a6d60018055565b6000612fae6131c8565b612fb66131f3565b612fbe61325f565b612fc88383613542565b60405190915083907f92f64ca637d023f354075a4be751b169c1a8a9ccb6d33cdd0cb352054399572790600090a261148660018055565b60006130096131c8565b6130116131f3565b8161301b8161323e565b61302361325f565b60405163113b4fbf60e31b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906389da7df890602401602060405180830381865afa15801561308b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130af9190614e2a565b90506130ba81614852565b6002546040516370a0823160e01b81523060048201529194506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061312c9190614e2a565b90508084111561314f5760405163569d45cf60e11b815260040160405180910390fd5b61317b7f00000000000000000000000000000000000000000000000000000000000000003330886137ee565b600254613192906001600160a01b031633866138f8565b60405184907fdcadafc28aac48a048c875f5f3127f2189b02d21291b563568cf8892a596bbb090600090a25050610cc560018055565b6005546001600160a01b03163314610fbe57604051631963d1e760e31b815260040160405180910390fd5b60005460ff1615610fbe5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064015b60405180910390fd5b806000036111d057604051639d635cff60e01b815260040160405180910390fd5b6002600154036132b15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401613235565b6002600155565b60405163b67e9df760e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b67e9df790602401602060405180830381865afa15801561331c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613340919061504e565b61335d5760405163d8d5894f60e01b815260040160405180910390fd5b600060075460085461336f9190614ee1565b9050818110156133925760405163569d45cf60e11b815260040160405180910390fd5b600061339c610a7b565b60405163140e25ad60e31b8152600481018590529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a0712d6890602401600060405180830381600087803b15801561340157600080fd5b505af1158015613415573d6000803e3d6000fd5b50505050826007600082825461342b9190614e9a565b909155505042600d558015613512576134e67f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166361d027b36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e09190614ef4565b836138f8565b60405181907fda0ff68ccd5fb797a8f86207386ea961ca6990c15ace2424ab51eb871ed4959990600090a25b60405183907f69c0ed5a77051ba5f0c42418bb6db6d3f73884dea69811c50bf320298df6ca5c90600090a2505050565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156135ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135cf9190614e2a565b90506135db848261483c565b9350836000036135fe5760405163569d45cf60e11b815260040160405180910390fd5b60405163113b4fbf60e31b815260048101859052613690907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906389da7df890602401602060405180830381865afa158015613667573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061368b9190614e2a565b614852565b9150600061369e838561490f565b905060006136aa61103c565b90506136d77f0000000000000000000000000000000000000000000000000000000000000000828861450f565b600254604051631c6d209760e11b81526001600160a01b0391821660048201526024810188905260448101849052908216906338da412e906064015b6020604051808303816000875af1158015613732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137569190614e2a565b9695505050505050565b600061148682600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137dd9190614f11565b6003546001600160a01b0316614933565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691613852919061542c565b6000604051808303816000865af19150503d806000811461388f576040519150601f19603f3d011682016040523d82523d6000602084013e613894565b606091505b50915091508180156138be5750805115806138be5750808060200190518101906138be919061504e565b6138f05760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b6044820152606401613235565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691613954919061542c565b6000604051808303816000865af19150503d8060008114613991576040519150601f19603f3d011682016040523d82523d6000602084013e613996565b606091505b50915091508180156139c05750805115806139c05750808060200190518101906139c0919061504e565b6139f15760405162461bcd60e51b815260206004820152600260248201526114d560f21b6044820152606401613235565b5050505050565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015613a5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a839190614e2a565b9050613a8f828261483c565b915081600003613ab25760405163569d45cf60e11b815260040160405180910390fd5b81600b5411613ac2576000613ad0565b81600b54613ad09190614ee1565b600b55600a5415801590613ae45750600b54155b15613aef5760006009555b6000613af9610a7b565b42600d559050613b098184614ee1565b9250826007541015613b25576007805460009091559250613b3d565b8260076000828254613b379190614ee1565b90915550505b613bbf7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166361d027b36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134bc573d6000803e3d6000fd5b613bea7f0000000000000000000000000000000000000000000000000000000000000000308561450f565b604051630852cd8d60e31b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c6890602401600060405180830381600087803b158015613c4c57600080fd5b505af1158015613c60573d6000803e3d6000fd5b50506040518592507f33a382daad6aace935340a474d09fec82af4bec7e2b69518d283231b03a65f249150600090a2613c97612516565b611a6d57611a6d60006012819055601355565b613cb261498d565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6002546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613d49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d6d9190614e2a565b9050613d79848261483c565b935083600003613d9c5760405163569d45cf60e11b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c1a2dad4613dd486613760565b6040518263ffffffff1660e01b8152600401613df291815260200190565b602060405180830381865afa158015613e0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e339190614e2a565b91506000613e41838561490f565b90506000613e4d61103c565b600254909150613e67906001600160a01b0316828861450f565b60025460405163231831c760e21b81526001600160a01b039182166004820152602481018890526044810184905290821690638c60c71c90606401613713565b6002546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613ef4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f189190614e2a565b6040516370a0823160e01b81523060048201529092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015613f7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fa39190614e2a565b90509091565b6002543090613fc3906001600160a01b03163383866137ee565b600254601754613fe0916001600160a01b0390811691168561450f565b601754614018907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03168461450f565b604080516003808252608082019092526000916020820160608036833701905050601a54815191925085918391610100900460ff1690811061405c5761405c61509e565b6020908102919091010152601a5481518491839160ff9091169081106140845761408461509e565b60209081029190910101526040805160028082526060820190925260009181602001602082028036833701905050601a5490915060ff610100820481169116116140ce57836140d0565b845b816000815181106140e3576140e361509e565b6020908102919091010152601a5460ff610100820481169116116141075784614109565b835b8160018151811061411c5761411c61509e565b6020026020010181815250506000600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561417d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141a19190614f11565b6141ac90600a615018565b601654600254604051632a6f500560e11b81526001600160a01b03918216600482015261010090920416906354dea00a90602401602060405180830381865afa1580156141fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142219190614e2a565b61422b9088614e59565b6142359190614e86565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015614297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142bb9190614f11565b6142c690600a615018565b601654604051632a6f500560e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152610100909204909116906354dea00a90602401602060405180830381865afa158015614336573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061435a9190614e2a565b6143649088614e59565b61436e9190614e86565b601a54909150600090620f424090614393906301000000900463ffffffff1682615448565b63ffffffff166143a38486614e9a565b6143ad9190614e59565b6143b79190614e86565b90506000600185836040516020016143d193929190615465565b60408051601f198184030181526019805460a060208202860181019094526080850181815292955060009493849392919084018282801561443b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161441d575b50505091835250506020810189905260408082018590526000606090920191909152601754601854915163172b958560e31b81529293506001600160a01b03169163b95cac2891614494918c90819087906004016151cd565b600060405180830381600087803b1580156144ae57600080fd5b505af11580156144c2573d6000803e3d6000fd5b5050505050505050505050505050565b6144da6131f3565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613cdf3390565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b179052915160009283929087169161456b919061542c565b6000604051808303816000865af19150503d80600081146145a8576040519150601f19603f3d011682016040523d82523d6000602084013e6145ad565b606091505b50915091508180156145d75750805115806145d75750808060200190518101906145d7919061504e565b6139f15760405162461bcd60e51b8152602060048201526002602482015261534160f01b6044820152606401613235565b614610612516565b61462d5760405163038cbd4b60e31b815260040160405180910390fd5b6002546040516370a0823160e01b81523060048201819052916000916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561467b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061469f9190614e2a565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918616906370a0823190602401602060405180830381865afa1580156146eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061470f9190614e2a565b6040516370a0823160e01b81526001600160a01b0385811660048301529192506000917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561477b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061479f9190614e2a565b9050808511156147de576147de7f000000000000000000000000000000000000000000000000000000000000000033866147d9858a614ee1565b6137ee565b6002546147f5906001600160a01b031633856138f8565b6148008633846138f8565b614809856139f8565b60405133907f1e1ef858062a7196d1891e397a5cde9891e6ddf61a81e9d269a3aaa7a95dacd890600090a2505050505050565b600081831061484b5781612d61565b5090919050565b600061148682600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156148ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148cf9190614f11565b60035460ff91909116906001600160a01b03166149d6565b601154610100900460ff16610fbe57604051634e751a9560e11b815260040160405180910390fd5b6000620f424061491f8382614ee1565b6149299085614e59565b612d619190614e86565b60008061493f83614a29565b9050600061494c84614a8d565b90506149588583615485565b61496390600a615018565b61496f6006600a615018565b6149798389614e59565b6149839190614e59565b6137569190614e86565b60005460ff16610fbe5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401613235565b6000806149e283614a29565b905060006149ef84614a8d565b90506149fd6006600a615018565b614a079082614e59565b614a148660ff8516614e9a565b614a1f90600a61549e565b6149839088614e59565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015614a69573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114869190614f11565b6000806000806000856001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015614ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614af791906154c4565b9450945050935093508369ffffffffffffffffffff168169ffffffffffffffffffff161015614b535760405162461bcd60e51b81526020600482015260086024820152674f6c64206461746160c01b6044820152606401613235565b60008211614b985760405162461bcd60e51b8152602060048201526012602482015271526f756e64206e6f7420636f6d706c65746560701b6044820152606401613235565b5090949350505050565b60005b83811015614bbd578181015183820152602001614ba5565b50506000910152565b60008151808452614bde816020860160208601614ba2565b601f01601f19169290920160200192915050565b602081526000612d616020830184614bc6565b80151581146111d057600080fd5b600080600060608486031215614c2857600080fd5b83359250602084013591506040840135614c4181614c05565b809150509250925092565b600060208284031215614c5e57600080fd5b5035919050565b60008060408385031215614c7857600080fd5b50508035926020909101359150565b600080600060608486031215614c9c57600080fd5b505081359360208301359350604090920135919050565b60008083601f840112614cc557600080fd5b50813567ffffffffffffffff811115614cdd57600080fd5b602083019150836020828501011115614cf557600080fd5b9250929050565b6000806000806000806000806000806000806101608d8f031215614d1f57600080fd5b8c359b5060208d01359a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d01359450614d626101008e0135614c05565b6101008d01359350614d786101208e0135614c05565b6101208d0135925067ffffffffffffffff6101408e01351115614d9a57600080fd5b614dab8e6101408f01358f01614cb3565b81935080925050509295989b509295989b509295989b565b600060208284031215614dd557600080fd5b813563ffffffff81168114612d6157600080fd5b6001600160a01b03811681146111d057600080fd5b60008060408385031215614e1157600080fd5b8235614e1c81614de9565b946020939093013593505050565b600060208284031215614e3c57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761148657611486614e43565b634e487b7160e01b600052601260045260246000fd5b600082614e9557614e95614e70565b500490565b8082018082111561148657611486614e43565b600181811c90821680614ec157607f821691505b602082108103610cc557634e487b7160e01b600052602260045260246000fd5b8181038181111561148657611486614e43565b600060208284031215614f0657600080fd5b8151612d6181614de9565b600060208284031215614f2357600080fd5b815160ff81168114612d6157600080fd5b600181815b80851115614f6f578160001904821115614f5557614f55614e43565b80851615614f6257918102915b93841c9390800290614f39565b509250929050565b600082614f8657506001611486565b81614f9357506000611486565b8160018114614fa95760028114614fb357614fcf565b6001915050611486565b60ff841115614fc457614fc4614e43565b50506001821b611486565b5060208310610133831016604e8410600b8410161715614ff2575081810a611486565b614ffc8383614f34565b806000190482111561501057615010614e43565b029392505050565b6000612d6160ff841683614f77565b818103600083128015838313168383128216171561504757615047614e43565b5092915050565b60006020828403121561506057600080fd5b8151612d6181614c05565b63ffffffff81811683821601908082111561504757615047614e43565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b600081518084526020808501945080840160005b838110156150fa578151875295820195908201906001016150de565b509495945050505050565b600060038510615117576151176150b4565b8482526060602083015261512e60608301856150ca565b9050826040830152949350505050565b8051608080845281519084018190526000916020919082019060a0860190845b818110156151835783516001600160a01b03168352928401929184019160010161515e565b50508285015191508581038387015261519c81836150ca565b92505050604083015184820360408601526151b78282614bc6565b9150506060830151610a73606086018215159052565b8481526001600160a01b038481166020830152831660408201526080606082018190526000906137569083018461513e565b6004811061520f5761520f6150b4565b9052565b61521d81846151ff565b60406020820152600061523360408301846150ca565b949350505050565b60ff818116838216029081169081811461504757615047614e43565b80820260008212600160ff1b8414161561527357615273614e43565b818105831482151761148657611486614e43565b60008261529657615296614e70565b600160ff1b8214600019841416156152b0576152b0614e43565b500590565b601f821115611a6d57600081815260208120601f850160051c810160208610156152dc5750805b601f850160051c820191505b818110156138f0578281556001016152e8565b67ffffffffffffffff83111561531357615313615088565b615327836153218354614ead565b836152b5565b6000601f84116001811461535b57600085156153435750838201355b600019600387901b1c1916600186901b1783556139f1565b600083815260209020601f19861690835b8281101561538c578685013582556020948501946001909201910161536c565b50868210156153a95760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60006101208c83528b60208401528a60408401528960608401528860808401528760a084015286151560c084015285151560e0840152806101008401528381840152506101408385828501376000838501820152601f909301601f19169091019091019a9950505050505050505050565b6000825161543e818460208701614ba2565b9190910192915050565b63ffffffff82811682821603908082111561504757615047614e43565b61546f81856151ff565b60606020820152600061512e60608301856150ca565b60ff818116838216019081111561148657611486614e43565b6000612d618383614f77565b805169ffffffffffffffffffff8116811461174857600080fd5b600080600080600060a086880312156154dc57600080fd5b6154e5866154aa565b9450602086015193506040860151925060608601519150615508608087016154aa565b9050929550929590935056fea264697066735822122021f79c36f78f3fbf1124a6c6b78e66f150d81578539f21bfb76c4d049695a03c64736f6c6343000813003300000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435740000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c3359000000000000000000000000fe4a8cc5b5b2366c1b58bea3858e81843581b2f70000000000000000000000004cd8a3df2536100ec552a37c813a9414123e1c0300000000000000000000000047671b43b6e05fc6f423595f625716a06d76d9ec000000000000000000000000000000000000000000000000000000000000001542616c616e636572204d61726b6574204d616b65720000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104075760003560e01c80636b64c76911610220578063ba2d034411610130578063de839ba4116100b8578063f686138d11610087578063f686138d146107dc578063f69aa3d5146107e5578063f95c1b26146107f8578063fa45d56214610805578063fbfa77cf1461081857600080fd5b8063de839ba41461079a578063ea8364aa146107a3578063f2674f22146107b6578063f3fef3a3146107c957600080fd5b8063c198f8ba116100ff578063c198f8ba14610765578063c5ebeaec1461076d578063c6beb58614610780578063d366a41f14610789578063d6fbf2021461079157600080fd5b8063ba2d03441461072f578063bb35212014610737578063bc5477ad14610740578063c0f4a0051461075357600080fd5b80639d7de6b3116101b3578063a516ed0211610182578063a516ed02146106fb578063a6a8f1f914610703578063a71891c31461070c578063ad81fced14610714578063b220a79b1461071d57600080fd5b80639d7de6b3146106c45780639e1b0045146106d7578063a1951665146106ea578063a38aaa90146106f357600080fd5b80638351faf5116101ef5780638351faf5146106835780638456cb59146106965780638d1d7c611461069e5780639cd441da146106b157600080fd5b80636b64c7691461064d578063717e794d146106555780637df1f1b91461065d57806381680d0a1461067057600080fd5b806329b154c31161031b5780633e032a3b116102ae5780634dc415de1161027d5780634dc415de1461060c5780635c975abb1461061457806361ab077f1461061f578063698996f81461063257806369ae990b1461063a57600080fd5b80633e032a3b146105c65780633e0dc34e146105f25780633f4ba83a146105fb57806348dcacab1461060357600080fd5b80633168b03f116102ea5780633168b03f1461057057806335faa41614610583578063371fd8e6146105aa57806339518b5e146105bd57600080fd5b806329b154c3146105395780632a9439451461054c5780632d76643c14610554578063311176d71461055d57600080fd5b80631370720f1161039e5780631de01bc91161036d5780631de01bc9146104ee57806323443944146104f757806325d9b7921461050157806329610252146105145780632982db001461051c57600080fd5b80631370720f1461049b57806314a6bf0f146104ae57806316f0115b146104b65780631c4695f4146104e657600080fd5b80630e5f5dbd116103da5780630e5f5dbd146104745780630f5e07c71461047c57806312bec0021461048557806312f21a1a1461049257600080fd5b8063018a25e81461040c57806306fdde0314610427578063095559aa1461043c5780630a2468711461044f575b600080fd5b61041461082b565b6040519081526020015b60405180910390f35b61042f610962565b60405161041e9190614bf2565b61041461044a366004614c13565b6109f0565b601a546104629062010000900460ff1681565b60405160ff909116815260200161041e565b610414610a7b565b61041460095481565b601a546104629060ff1681565b610414600d5481565b6104146104a9366004614c4c565b610ae0565b610414610ccb565b6016546104ce9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161041e565b61042f610ce7565b610414600a5481565b6104ff610cf4565b005b6104ce61050f366004614c4c565b610ddd565b6104ff610e07565b6016546105299060ff1681565b604051901515815260200161041e565b6104ff610547366004614c4c565b610fc0565b6104ce61103c565b61041460075481565b6002546104ce906001600160a01b031681565b6104ff61057e366004614c4c565b6110c0565b6104ce7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357481565b6104ff6105b8366004614c4c565b6111ae565b61041460125481565b601a546105dd906301000000900463ffffffff1681565b60405163ffffffff909116815260200161041e565b61041460185481565b6104ff6111d3565b610414600b5481565b6104ff61132f565b60005460ff16610529565b61041461062d366004614c65565b61142b565b61041461148c565b610414610648366004614c4c565b611606565b6104ff61174d565b6104146117f3565b6005546104ce906001600160a01b031681565b61041461067e366004614c13565b6118a6565b6104ff610691366004614c87565b6118f6565b6104ff611a72565b6003546104ce906001600160a01b031681565b6104ff6106bf366004614c65565b611bce565b6104ff6106d2366004614c65565b611cfb565b6104ff6106e5366004614c65565b612211565b61041460105481565b610529612516565b6104ff61255c565b61041460155481565b61041461259f565b61041460085481565b601a5461046290610100900460ff1681565b6104146127d3565b61041460145481565b6104ff61074e366004614c87565b612890565b60115461052990610100900460ff1681565b6104ff612bb6565b6104ff61077b366004614c4c565b612c03565b61041460065481565b610414612c61565b61041460135481565b610414600c5481565b6104ff6107b1366004614cfc565b612d68565b6104ff6107c4366004614dc3565b612e27565b6104ff6107d7366004614dfe565b612e86565b610414600f5481565b6104146107f3366004614c65565b612fa4565b6011546105299060ff1681565b610414610813366004614c4c565b612fff565b6017546104ce906001600160a01b031681565b6000807f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663dc38679c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b09190614e2a565b9050620f424062ffffff16817f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663e19538476040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093e9190614e2a565b6109489190614e59565b6109529190614e86565b61095c9082614e9a565b91505090565b6004805461096f90614ead565b80601f016020809104026020016040519081016040528092919081815260200182805461099b90614ead565b80156109e85780601f106109bd576101008083540402835291602001916109e8565b820191906000526020600020905b8154815290600101906020018083116109cb57829003601f168201915b505050505081565b60006109fa6131c8565b610a026131f3565b83610a0c8161323e565b610a1461325f565b610a1d856132b8565b8215610a3457610a2d8585613542565b9150610a40565b610a3d85612fff565b91505b600654610a4b612c61565b1215610a6a5760405163374c72ff60e11b815260040160405180910390fd5b610a7360018055565b509392505050565b60075460009015610ada57600062015180600d5442610a9a9190614ee1565b610aa49190614e86565b9050610ab5620f424061016d614e59565b81600c54600754610ac69190614e59565b610ad09190614e59565b61095c9190614e86565b50600090565b6000610aea6131c8565b610af26131f3565b81610afc8161323e565b610b0461325f565b6000610b0f84613760565b604051633068b6b560e21b8152600481018290529091507f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b03169063c1a2dad490602401602060405180830381865afa158015610b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9b9190614e2a565b6040516370a0823160e01b81523060048201529093506000906001600160a01b037f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357416906370a0823190602401602060405180830381865afa158015610c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c299190614e2a565b905080841115610c4c5760405163569d45cf60e11b815260040160405180910390fd5b600254610c64906001600160a01b03163330886137ee565b610c8f7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357433866138f8565b60405184907fbc87b68cd9f40bbab98db9b9e4d393c4ef32d4660271a908b81cfa10d8a59df990600090a25050610cc560018055565b50919050565b6000610cd5610a7b565b600754610ce29190614e9a565b905090565b600e805461096f90614ead565b7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d769190614ef4565b6001600160a01b0316336001600160a01b031614610da75760405163698bba4b60e01b815260040160405180910390fd5b6000600b81905560098190556040517f219124ae95cc25cf220d998f2867d37fb4ab4908cce7c51adfa33ce747aa5747908290a2565b60198181548110610ded57600080fd5b6000918252602090912001546001600160a01b0316905081565b610e0f6131c8565b610e1761325f565b6000610e21610a7b565b42600d556040516370a0823160e01b81523060048201529091506000907f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316906370a0823190602401602060405180830381865afa158015610e8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb39190614e2a565b905080821115610ed5576040516206230160eb1b815260040160405180910390fd5b8115610fb357610f877f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435747f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b03166361d027b36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f819190614ef4565b846138f8565b60405182907fda0ff68ccd5fb797a8f86207386ea961ca6990c15ace2424ab51eb871ed4959990600090a25b5050610fbe60018055565b565b336001600160a01b037f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357416146110095760405163bc9eca6160e01b815260040160405180910390fd5b600781905560405181907f35ba42ee3c2daa6cf14836eefff16b184565798767ec1e5d723008848aeaf7e390600090a250565b60007f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316632a9439456040518163ffffffff1660e01b8152600401602060405180830381865afa15801561109c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce29190614ef4565b7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561111e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111429190614ef4565b6001600160a01b0316336001600160a01b0316146111735760405163698bba4b60e01b815260040160405180910390fd5b60088190556040518181527f7760d892a7883522367f0eaea35e968381a018418c249cd9aaaca190fe5d88179060200160405180910390a150565b6111b66131c8565b6111be61325f565b6111c7816139f8565b6111d060018055565b50565b7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663baf4a3126040518163ffffffff1660e01b8152600401602060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112559190614ef4565b6001600160a01b0316336001600160a01b03161415801561130957507f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f39190614ef4565b6001600160a01b0316336001600160a01b031614155b1561132757604051631e1c735b60e21b815260040160405180910390fd5b610fbe613caa565b7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561138d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b19190614ef4565b6001600160a01b0316336001600160a01b0316146113e257604051632d5be4cb60e21b815260040160405180910390fd5b6011805461ff0019166101001790556005546040516001600160a01b03909116907faf77f8960cf590e245ec8b6d41c193a5dcacad8986ae4eb57ac9e5be7b6af03190600090a2565b60006114356131c8565b61143d6131f3565b61144561325f565b61144f8383613cfc565b60405190915081907f4e08ba899977cf7d4c2964bce71c6b9a7ef76ee5166a4c1249a1e08016e33ef190600090a261148660018055565b92915050565b6000806000611499613ea7565b60405163113b4fbf60e31b81526004810182905291935091506000906001600160a01b037f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357416906389da7df890602401602060405180830381865afa158015611506573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152a9190614e2a565b9050600061153784613760565b905060007f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b03166389da7df8611572610a7b565b6040518263ffffffff1660e01b815260040161159091815260200190565b602060405180830381865afa1580156115ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d19190614e2a565b90508083836115de61259f565b6115e89190614e9a565b6115f29190614e9a565b6115fc9190614ee1565b9550505050505090565b600061161061325f565b61161861082b565b7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169a9190614f11565b6116a590600a615018565b6116ae84613760565b6116b89190614e59565b6116c29190614e86565b90506116d76116d2826002614e59565b6132b8565b6116e18282613fa9565b61170c7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357433836138f8565b6040518281527f6e19477745f02fa64cb79e709afd8b6a5da159ef7b135546eafd67c38e425c439060200160405180910390a161174860018055565b919050565b61175561325f565b61175d612516565b61177a5760405163038cbd4b60e31b815260040160405180910390fd5b60165460ff16158061178e57506000601354115b156117ac5760405163829e373360e01b815260040160405180910390fd5b426012556006546000906117c390620f4240614ee1565b905080620f42406117d2610ccb565b6117dc9190614e59565b6117e69190614e86565b60135550610fbe60018055565b6000807f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b03166389da7df86007546040518263ffffffff1660e01b815260040161184691815260200190565b602060405180830381865afa158015611863573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118879190614e2a565b9050600061189361148c565b905061189f8282615027565b9250505090565b60006118b06131c8565b6118b86131f3565b836118c28161323e565b6118ca61325f565b82156118e1576118da8585613cfc565b91506118ed565b6118ea85610ae0565b91505b610a6a826139f8565b6118fe61325f565b7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561195c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119809190614ef4565b6001600160a01b0316336001600160a01b0316146119b15760405163698bba4b60e01b815260040160405180910390fd5b60115460ff166119d4576040516305b02a1960e01b815260040160405180910390fd5b6010548310156119f7576040516312cd610d60e21b815260040160405180910390fd5b611a00836132b8565b6000611a0c8483613542565b9050600f54611a19612c61565b1215611a38576040516378764b0f60e01b815260040160405180910390fd5b60405184907f8f77e6a87a8210bff9857b08990b1f360b73d6e92d422a9a0e2c78e449682a9c90600090a250611a6d60018055565b505050565b7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663baf4a3126040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ad0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af49190614ef4565b6001600160a01b0316336001600160a01b031614158015611ba857507f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b929190614ef4565b6001600160a01b0316336001600160a01b031614155b15611bc657604051631e1c735b60e21b815260040160405180910390fd5b610fbe6144d2565b611bd661325f565b611bde6131c8565b60003090507f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316632b4818836040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c65919061504e565b15611c7e578115611c7957611c79826132b8565b611caa565b611caa7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435743383856137ee565b611cb48383613fa9565b60408051848152602081018490527f38f8a0c92f4c5b0b6877f878cb4c0c8d348a47b76d716c8e78f425043df9515b910160405180910390a150611cf760018055565b5050565b611d0361325f565b611d0b6131c8565b6002546040805163313ce56760e01b8152905130926000926001600160a01b039091169163313ce567916004808201926020929091908290030181865afa158015611d5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7e9190614f11565b611d8990600a615018565b601654600254604051632a6f500560e11b81526001600160a01b03918216600482015261010090920416906354dea00a90602401602060405180830381865afa158015611dda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfe9190614e2a565b611e089086614e59565b611e129190614e86565b905060007f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e989190614f11565b611ea390600a615018565b601654604051632a6f500560e11b81526001600160a01b037f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357481166004830152610100909204909116906354dea00a90602401602060405180830381865afa158015611f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f379190614e2a565b611f419086614e59565b611f4b9190614e86565b601a54909150600090620f424090611f70906301000000900463ffffffff168261506b565b63ffffffff16611f808486614e9a565b611f8a9190614e59565b611f949190614e86565b60408051600380825260808201909252919250600091906020820160608036833701905050601a54815191925088918391610100900460ff16908110611fdc57611fdc61509e565b6020908102919091010152601a5481518791839160ff9091169081106120045761200461509e565b60209081029190910101526040805160028082526060820190925260009181602001602082028036833701905050601a5490915060ff6101008204811691161161204e5786612050565b875b816000815181106120635761206361509e565b6020908102919091010152601a5460ff610100820481169116116120875787612089565b865b8160018151811061209c5761209c61509e565b6020026020010181815250506000600182856040516020016120c093929190615105565b60408051601f198184030181526019805460a060208202860181019094526080850181815292955060009493849392919084018282801561212a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161210c575b505050918352505060208101869052604080820185905260006060909201919091526017546018549151638bdb391360e01b81529293506001600160a01b031691638bdb391391612183918c90819087906004016151cd565b600060405180830381600087803b15801561219d57600080fd5b505af11580156121b1573d6000803e3d6000fd5b5050505060008911156121c7576121c7896139f8565b604080518b8152602081018b90527f6f0f96292ae0038c04f9b6bab30f185d9ca02c471d0983f563f2a4f674aef137910160405180910390a15050505050505050611cf760018055565b61221961325f565b6122216131c8565b600254309061223b906001600160a01b03163383866137ee565b600254601754612258916001600160a01b0390811691168561450f565b601754612290907f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d43574906001600160a01b03168461450f565b7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316632b4818836040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612312919061504e565b1561232557612320826132b8565b612351565b6123517f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435743383856137ee565b604080516003808252608082019092526000916020820160608036833701905050601a548151919250600160701b91839162010000900460ff1690811061239a5761239a61509e565b6020026020010181815250508381601a60019054906101000a900460ff1660ff16815181106123cb576123cb61509e565b6020908102919091010152601a5481518491839160ff9091169081106123f3576123f361509e565b60200260200101818152505060008082604051602001612414929190615213565b60408051601f198184030181526019805460a060208202860181019094526080850181815292955060009493849392919084018282801561247e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612460575b50505091835250506020810185905260408082018590526000606090920191909152601754601854915163172b958560e31b81529293506001600160a01b03169163b95cac28916124d7918890819087906004016151cd565b600060405180830381600087803b1580156124f157600080fd5b505af1158015612505573d6000803e3d6000fd5b5050505050505050611cf760018055565b600080600a5411801561252b57506000600b54115b8015612538575060095442115b80610ce257506000600754118015610ce25750600654612556612c61565b12905090565b61256461325f565b601254600003612587576040516334dc687f60e11b815260040160405180910390fd5b60006125916127d3565b90506000610fb38183614608565b6016546040516370a0823160e01b815230600482015260009182916101009091046001600160a01b0316906370a0823190602401602060405180830381865afa1580156125f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126149190614e2a565b90506000601660019054906101000a90046001600160a01b03166001600160a01b031663679aefce6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561266b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268f9190614e2a565b90506000601660019054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270a9190614f11565b61271590600261523b565b61272090600a615018565b600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612773573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127979190614f11565b6127a290600a615018565b6127ac8486614e59565b6127b69190614e59565b6127c09190614e86565b90506127cb81613760565b935050505090565b600080620f4240601554620f42406127eb9190614ee1565b6007546127f89190614e59565b6128029190614e86565b9050600061012c601254426128179190614ee1565b6128219190614e86565b90506000601454826128339190614e59565b9050620f424081111561284857509092915050565b600061285782620f4240614ee1565b90506000620f42408260135461286d9190614e59565b6128779190614e86565b905080851161288657806115fc565b5092949350505050565b61289861325f565b7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061291a9190614ef4565b6001600160a01b0316336001600160a01b03161461294b5760405163698bba4b60e01b815260040160405180910390fd5b600080612956613ea7565b91509150600061296e612967610ccb565b879061483c565b600a549091501561298f57600a546129869042614e9a565b600955600b8190555b80821015612ad95760006129a38383614ee1565b60405163113b4fbf60e31b8152600481018290529091506000906001600160a01b037f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357416906389da7df890602401602060405180830381865afa158015612a0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a329190614e2a565b90506000612a3f82614852565b905085811115612a5657612a566111d08783614ee1565b6002546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac39190614e2a565b1115612ad557612ad38188613cfc565b505b5050505b6040516370a0823160e01b81523060048201526000907f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316906370a0823190602401602060405180830381865afa158015612b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b649190614e2a565b118015612b715750600081115b15612b7f57612b7f816139f8565b60405186907fdfcd68ceed46252749a4089f344aec4b4ee7f28a068f704c21799355325f3da990600090a2505050611a6d60018055565b612bbe6131c8565b6011805461ff00191690556005546040516001600160a01b03909116907facf29ad8d63913d38e7e1176963a4afb76bf0918516051da68408ecb6f98065d90600090a2565b612c0b6131c8565b612c136131f3565b80612c1d8161323e565b612c2561325f565b612c2e826132b8565b600654612c39612c61565b1215612c585760405163374c72ff60e11b815260040160405180910390fd5b611cf760018055565b600080612c6c61148c565b905080600003612c915760075415612c8957620f423f1991505090565b600091505090565b60075460405163113b4fbf60e31b81526000916001600160a01b037f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357416916389da7df891612ce59160040190815260200190565b602060405180830381865afa158015612d02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d269190614e2a565b9050600082612d358382615027565b612d4290620f4240615257565b612d4c9190615287565b9050620f423f19811215612d615750620f423f195b9392505050565b612d706131c8565b612d786148e7565b60068c9055600c8b905560088a90556014899055600a889055600f879055601086905560158590556011805460ff199081168615151790915560168054909116841515179055600e612dcb8284836152fb565b508a8c7fed1352796b02006c8bf7ef68956cb9fc55c08f9193eee9cec7ee590840bbbaad8c6014548c8c8c8c8c8c8c8c604051612e119a999897969594939291906153bb565b60405180910390a3505050505050505050505050565b612e2f61325f565b612e376131c8565b620f424063ffffffff82161115612e6157604051630f4ec00b60e01b815260040160405180910390fd5b601a805466ffffffff0000001916630100000063ffffffff8416021790556001805550565b612e8e6131c8565b612e966131f3565b80612ea08161323e565b612ea861325f565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015612eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f139190614e2a565b905080831115612f21578092505b612f2c8433856138f8565b6000600754118015612f465750600654612f44612c61565b125b15612f645760405163374c72ff60e11b815260040160405180910390fd5b60405183906001600160a01b038616907f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d590600090a350611a6d60018055565b6000612fae6131c8565b612fb66131f3565b612fbe61325f565b612fc88383613542565b60405190915083907f92f64ca637d023f354075a4be751b169c1a8a9ccb6d33cdd0cb352054399572790600090a261148660018055565b60006130096131c8565b6130116131f3565b8161301b8161323e565b61302361325f565b60405163113b4fbf60e31b8152600481018490526000907f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316906389da7df890602401602060405180830381865afa15801561308b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130af9190614e2a565b90506130ba81614852565b6002546040516370a0823160e01b81523060048201529194506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061312c9190614e2a565b90508084111561314f5760405163569d45cf60e11b815260040160405180910390fd5b61317b7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435743330886137ee565b600254613192906001600160a01b031633866138f8565b60405184907fdcadafc28aac48a048c875f5f3127f2189b02d21291b563568cf8892a596bbb090600090a25050610cc560018055565b6005546001600160a01b03163314610fbe57604051631963d1e760e31b815260040160405180910390fd5b60005460ff1615610fbe5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064015b60405180910390fd5b806000036111d057604051639d635cff60e01b815260040160405180910390fd5b6002600154036132b15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401613235565b6002600155565b60405163b67e9df760e01b81523060048201527f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b03169063b67e9df790602401602060405180830381865afa15801561331c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613340919061504e565b61335d5760405163d8d5894f60e01b815260040160405180910390fd5b600060075460085461336f9190614ee1565b9050818110156133925760405163569d45cf60e11b815260040160405180910390fd5b600061339c610a7b565b60405163140e25ad60e31b8152600481018590529091507f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b03169063a0712d6890602401600060405180830381600087803b15801561340157600080fd5b505af1158015613415573d6000803e3d6000fd5b50505050826007600082825461342b9190614e9a565b909155505042600d558015613512576134e67f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435747f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b03166361d027b36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e09190614ef4565b836138f8565b60405181907fda0ff68ccd5fb797a8f86207386ea961ca6990c15ace2424ab51eb871ed4959990600090a25b60405183907f69c0ed5a77051ba5f0c42418bb6db6d3f73884dea69811c50bf320298df6ca5c90600090a2505050565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357416906370a0823190602401602060405180830381865afa1580156135ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135cf9190614e2a565b90506135db848261483c565b9350836000036135fe5760405163569d45cf60e11b815260040160405180910390fd5b60405163113b4fbf60e31b815260048101859052613690907f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316906389da7df890602401602060405180830381865afa158015613667573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061368b9190614e2a565b614852565b9150600061369e838561490f565b905060006136aa61103c565b90506136d77f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d43574828861450f565b600254604051631c6d209760e11b81526001600160a01b0391821660048201526024810188905260448101849052908216906338da412e906064015b6020604051808303816000875af1158015613732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137569190614e2a565b9695505050505050565b600061148682600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137dd9190614f11565b6003546001600160a01b0316614933565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691613852919061542c565b6000604051808303816000865af19150503d806000811461388f576040519150601f19603f3d011682016040523d82523d6000602084013e613894565b606091505b50915091508180156138be5750805115806138be5750808060200190518101906138be919061504e565b6138f05760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b6044820152606401613235565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691613954919061542c565b6000604051808303816000865af19150503d8060008114613991576040519150601f19603f3d011682016040523d82523d6000602084013e613996565b606091505b50915091508180156139c05750805115806139c05750808060200190518101906139c0919061504e565b6139f15760405162461bcd60e51b815260206004820152600260248201526114d560f21b6044820152606401613235565b5050505050565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316906370a0823190602401602060405180830381865afa158015613a5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a839190614e2a565b9050613a8f828261483c565b915081600003613ab25760405163569d45cf60e11b815260040160405180910390fd5b81600b5411613ac2576000613ad0565b81600b54613ad09190614ee1565b600b55600a5415801590613ae45750600b54155b15613aef5760006009555b6000613af9610a7b565b42600d559050613b098184614ee1565b9250826007541015613b25576007805460009091559250613b3d565b8260076000828254613b379190614ee1565b90915550505b613bbf7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435747f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b03166361d027b36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134bc573d6000803e3d6000fd5b613bea7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d43574308561450f565b604051630852cd8d60e31b8152600481018490527f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316906342966c6890602401600060405180830381600087803b158015613c4c57600080fd5b505af1158015613c60573d6000803e3d6000fd5b50506040518592507f33a382daad6aace935340a474d09fec82af4bec7e2b69518d283231b03a65f249150600090a2613c97612516565b611a6d57611a6d60006012819055601355565b613cb261498d565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6002546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613d49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d6d9190614e2a565b9050613d79848261483c565b935083600003613d9c5760405163569d45cf60e11b815260040160405180910390fd5b7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663c1a2dad4613dd486613760565b6040518263ffffffff1660e01b8152600401613df291815260200190565b602060405180830381865afa158015613e0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e339190614e2a565b91506000613e41838561490f565b90506000613e4d61103c565b600254909150613e67906001600160a01b0316828861450f565b60025460405163231831c760e21b81526001600160a01b039182166004820152602481018890526044810184905290821690638c60c71c90606401613713565b6002546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613ef4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f189190614e2a565b6040516370a0823160e01b81523060048201529092507f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b0316906370a0823190602401602060405180830381865afa158015613f7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fa39190614e2a565b90509091565b6002543090613fc3906001600160a01b03163383866137ee565b600254601754613fe0916001600160a01b0390811691168561450f565b601754614018907f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d43574906001600160a01b03168461450f565b604080516003808252608082019092526000916020820160608036833701905050601a54815191925085918391610100900460ff1690811061405c5761405c61509e565b6020908102919091010152601a5481518491839160ff9091169081106140845761408461509e565b60209081029190910101526040805160028082526060820190925260009181602001602082028036833701905050601a5490915060ff610100820481169116116140ce57836140d0565b845b816000815181106140e3576140e361509e565b6020908102919091010152601a5460ff610100820481169116116141075784614109565b835b8160018151811061411c5761411c61509e565b6020026020010181815250506000600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561417d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141a19190614f11565b6141ac90600a615018565b601654600254604051632a6f500560e11b81526001600160a01b03918216600482015261010090920416906354dea00a90602401602060405180830381865afa1580156141fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142219190614e2a565b61422b9088614e59565b6142359190614e86565b905060007f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435746001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015614297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142bb9190614f11565b6142c690600a615018565b601654604051632a6f500560e11b81526001600160a01b037f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357481166004830152610100909204909116906354dea00a90602401602060405180830381865afa158015614336573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061435a9190614e2a565b6143649088614e59565b61436e9190614e86565b601a54909150600090620f424090614393906301000000900463ffffffff1682615448565b63ffffffff166143a38486614e9a565b6143ad9190614e59565b6143b79190614e86565b90506000600185836040516020016143d193929190615465565b60408051601f198184030181526019805460a060208202860181019094526080850181815292955060009493849392919084018282801561443b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161441d575b50505091835250506020810189905260408082018590526000606090920191909152601754601854915163172b958560e31b81529293506001600160a01b03169163b95cac2891614494918c90819087906004016151cd565b600060405180830381600087803b1580156144ae57600080fd5b505af11580156144c2573d6000803e3d6000fd5b5050505050505050505050505050565b6144da6131f3565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613cdf3390565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b179052915160009283929087169161456b919061542c565b6000604051808303816000865af19150503d80600081146145a8576040519150601f19603f3d011682016040523d82523d6000602084013e6145ad565b606091505b50915091508180156145d75750805115806145d75750808060200190518101906145d7919061504e565b6139f15760405162461bcd60e51b8152602060048201526002602482015261534160f01b6044820152606401613235565b614610612516565b61462d5760405163038cbd4b60e31b815260040160405180910390fd5b6002546040516370a0823160e01b81523060048201819052916000916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561467b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061469f9190614e2a565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918616906370a0823190602401602060405180830381865afa1580156146eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061470f9190614e2a565b6040516370a0823160e01b81526001600160a01b0385811660048301529192506000917f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357416906370a0823190602401602060405180830381865afa15801561477b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061479f9190614e2a565b9050808511156147de576147de7f000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d4357433866147d9858a614ee1565b6137ee565b6002546147f5906001600160a01b031633856138f8565b6148008633846138f8565b614809856139f8565b60405133907f1e1ef858062a7196d1891e397a5cde9891e6ddf61a81e9d269a3aaa7a95dacd890600090a2505050505050565b600081831061484b5781612d61565b5090919050565b600061148682600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156148ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148cf9190614f11565b60035460ff91909116906001600160a01b03166149d6565b601154610100900460ff16610fbe57604051634e751a9560e11b815260040160405180910390fd5b6000620f424061491f8382614ee1565b6149299085614e59565b612d619190614e86565b60008061493f83614a29565b9050600061494c84614a8d565b90506149588583615485565b61496390600a615018565b61496f6006600a615018565b6149798389614e59565b6149839190614e59565b6137569190614e86565b60005460ff16610fbe5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401613235565b6000806149e283614a29565b905060006149ef84614a8d565b90506149fd6006600a615018565b614a079082614e59565b614a148660ff8516614e9a565b614a1f90600a61549e565b6149839088614e59565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015614a69573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114869190614f11565b6000806000806000856001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015614ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614af791906154c4565b9450945050935093508369ffffffffffffffffffff168169ffffffffffffffffffff161015614b535760405162461bcd60e51b81526020600482015260086024820152674f6c64206461746160c01b6044820152606401613235565b60008211614b985760405162461bcd60e51b8152602060048201526012602482015271526f756e64206e6f7420636f6d706c65746560701b6044820152606401613235565b5090949350505050565b60005b83811015614bbd578181015183820152602001614ba5565b50506000910152565b60008151808452614bde816020860160208601614ba2565b601f01601f19169290920160200192915050565b602081526000612d616020830184614bc6565b80151581146111d057600080fd5b600080600060608486031215614c2857600080fd5b83359250602084013591506040840135614c4181614c05565b809150509250925092565b600060208284031215614c5e57600080fd5b5035919050565b60008060408385031215614c7857600080fd5b50508035926020909101359150565b600080600060608486031215614c9c57600080fd5b505081359360208301359350604090920135919050565b60008083601f840112614cc557600080fd5b50813567ffffffffffffffff811115614cdd57600080fd5b602083019150836020828501011115614cf557600080fd5b9250929050565b6000806000806000806000806000806000806101608d8f031215614d1f57600080fd5b8c359b5060208d01359a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d01359450614d626101008e0135614c05565b6101008d01359350614d786101208e0135614c05565b6101208d0135925067ffffffffffffffff6101408e01351115614d9a57600080fd5b614dab8e6101408f01358f01614cb3565b81935080925050509295989b509295989b509295989b565b600060208284031215614dd557600080fd5b813563ffffffff81168114612d6157600080fd5b6001600160a01b03811681146111d057600080fd5b60008060408385031215614e1157600080fd5b8235614e1c81614de9565b946020939093013593505050565b600060208284031215614e3c57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761148657611486614e43565b634e487b7160e01b600052601260045260246000fd5b600082614e9557614e95614e70565b500490565b8082018082111561148657611486614e43565b600181811c90821680614ec157607f821691505b602082108103610cc557634e487b7160e01b600052602260045260246000fd5b8181038181111561148657611486614e43565b600060208284031215614f0657600080fd5b8151612d6181614de9565b600060208284031215614f2357600080fd5b815160ff81168114612d6157600080fd5b600181815b80851115614f6f578160001904821115614f5557614f55614e43565b80851615614f6257918102915b93841c9390800290614f39565b509250929050565b600082614f8657506001611486565b81614f9357506000611486565b8160018114614fa95760028114614fb357614fcf565b6001915050611486565b60ff841115614fc457614fc4614e43565b50506001821b611486565b5060208310610133831016604e8410600b8410161715614ff2575081810a611486565b614ffc8383614f34565b806000190482111561501057615010614e43565b029392505050565b6000612d6160ff841683614f77565b818103600083128015838313168383128216171561504757615047614e43565b5092915050565b60006020828403121561506057600080fd5b8151612d6181614c05565b63ffffffff81811683821601908082111561504757615047614e43565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b600081518084526020808501945080840160005b838110156150fa578151875295820195908201906001016150de565b509495945050505050565b600060038510615117576151176150b4565b8482526060602083015261512e60608301856150ca565b9050826040830152949350505050565b8051608080845281519084018190526000916020919082019060a0860190845b818110156151835783516001600160a01b03168352928401929184019160010161515e565b50508285015191508581038387015261519c81836150ca565b92505050604083015184820360408601526151b78282614bc6565b9150506060830151610a73606086018215159052565b8481526001600160a01b038481166020830152831660408201526080606082018190526000906137569083018461513e565b6004811061520f5761520f6150b4565b9052565b61521d81846151ff565b60406020820152600061523360408301846150ca565b949350505050565b60ff818116838216029081169081811461504757615047614e43565b80820260008212600160ff1b8414161561527357615273614e43565b818105831482151761148657611486614e43565b60008261529657615296614e70565b600160ff1b8214600019841416156152b0576152b0614e43565b500590565b601f821115611a6d57600081815260208120601f850160051c810160208610156152dc5750805b601f850160051c820191505b818110156138f0578281556001016152e8565b67ffffffffffffffff83111561531357615313615088565b615327836153218354614ead565b836152b5565b6000601f84116001811461535b57600085156153435750838201355b600019600387901b1c1916600186901b1783556139f1565b600083815260209020601f19861690835b8281101561538c578685013582556020948501946001909201910161536c565b50868210156153a95760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60006101208c83528b60208401528a60408401528960608401528860808401528760a084015286151560c084015285151560e0840152806101008401528381840152506101408385828501376000838501820152601f909301601f19169091019091019a9950505050505050505050565b6000825161543e818460208701614ba2565b9190910192915050565b63ffffffff82811682821603908082111561504757615047614e43565b61546f81856151ff565b60606020820152600061512e60608301856150ca565b60ff818116838216019081111561148657611486614e43565b6000612d618383614f77565b805169ffffffffffffffffffff8116811461174857600080fd5b600080600080600060a086880312156154dc57600080fd5b6154e5866154aa565b9450602086015193506040860151925060608601519150615508608087016154aa565b9050929550929590935056fea264697066735822122021f79c36f78f3fbf1124a6c6b78e66f150d81578539f21bfb76c4d049695a03c64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d435740000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c3359000000000000000000000000fe4a8cc5b5b2366c1b58bea3858e81843581b2f70000000000000000000000004cd8a3df2536100ec552a37c813a9414123e1c0300000000000000000000000047671b43b6e05fc6f423595f625716a06d76d9ec000000000000000000000000000000000000000000000000000000000000001542616c616e636572204d61726b6574204d616b65720000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): Balancer Market Maker
Arg [1] : _sweep (address): 0xB88a5Ac00917a02d82c7cd6CEBd73E2852d43574
Arg [2] : _usdx (address): 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359
Arg [3] : _oracleUsdx (address): 0xfE4A8cc5b5B2366C1B58Bea3858e81843581b2F7
Arg [4] : _poolAddress (address): 0x4CD8a3Df2536100EC552a37C813A9414123e1c03
Arg [5] : _borrower (address): 0x47671b43B6E05FC6f423595F625716A06d76D9Ec
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [1] : 000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d43574
Arg [2] : 0000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c3359
Arg [3] : 000000000000000000000000fe4a8cc5b5b2366c1b58bea3858e81843581b2f7
Arg [4] : 0000000000000000000000004cd8a3df2536100ec552a37c813a9414123e1c03
Arg [5] : 00000000000000000000000047671b43b6e05fc6f423595f625716a06d76d9ec
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000015
Arg [7] : 42616c616e636572204d61726b6574204d616b65720000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.