Contract Overview
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x714cbe0d0aad9d9fee79293b0bf0d87108da6b70f17ed8d986c95313c7edb425 | Buy Sweep | 7247375 | 8 hrs 35 mins ago | 0x68b2a7b9ca1d8c87a170e9bb2e120cfd09ef144f | IN | 0x7560d15774499386b04a64177e090b33e803493f | 0 ETH | 0.001227663985 | |
0x0951dfe6758f361f68b13b617c9221d05792af74ff3e3fde6ce7292c31d7c4ed | Buy Sweep | 7245708 | 9 hrs 31 mins ago | 0x68b2a7b9ca1d8c87a170e9bb2e120cfd09ef144f | IN | 0x7560d15774499386b04a64177e090b33e803493f | 0 ETH | 0.001259596695 | |
0x9337d3abad7b6d6d6839088825cdd41f9c0608f8414f597ef25860131a10f835 | Buy Sweep | 7244285 | 10 hrs 18 mins ago | 0x68b2a7b9ca1d8c87a170e9bb2e120cfd09ef144f | IN | 0x7560d15774499386b04a64177e090b33e803493f | 0 ETH | 0.001339468324 | |
0xe27cb41b26ca46328b0e9055b8dfe94da42bcdd152d49fbdf8ab9fc67197fb38 | 0x60a06040 | 6727181 | 12 days 9 hrs ago | 0x8610f105f3d0a0479d9c9d85c13b352f6c8eefee | IN | Create: BalancerMarketMaker | 0 ETH | 0.010827335768 |
[ Download CSV Export ]
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: 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 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 poolFee() external view returns (uint24); 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 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); } 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: 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/Balancer/IBalancer.sol"; contract BalancerMarketMaker is Stabilizer { error BadAddress(address asset); 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; 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) { 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 Current Value of investment. * @return total with 6 decimal to be compatible with dollar coins. */ function currentValue() public view override returns (uint256) { uint256 accruedFeeInUSD = sweep.convertToUSD(accruedFee()); return assetValue() + super.currentValue() - accruedFeeInUSD; } /** * @notice Gets the asset price of AMM * @return the amm usdx amount */ function assetValue() public view 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); } /* ========== Actions ========== */ function buySweep(uint256 sweepAmount, uint256 slippage) external nonReentrant { uint256 sweepAvailable = sweep.minters(address(this)).maxAmount - sweepBorrowed; if (sweepAvailable < sweepAmount*2) revert NotEnoughBalance(); uint256 targetPrice = _oracleUsdToUsdx(sweep.targetPrice()); uint256 buyPrice = targetPrice + ((sweep.arbSpread() * targetPrice) / PRECISION); uint256 usdxAmount = (sweepAmount * buyPrice) / (10 ** sweep.decimals()); TransferHelper.safeTransferFrom(address(usdx), msg.sender, address(this), usdxAmount); TransferHelper.safeApprove(address(usdx), address(vault), usdxAmount); TransferHelper.safeApprove(address(sweep), address(vault), sweepAmount); _borrow(sweepAmount*2); _addLiquidity(usdxAmount, sweepAmount, slippage); TransferHelper.safeTransfer(address(sweep), msg.sender, sweepAmount); emit SweepPurchased(usdxAmount); } function initPool(uint256 usdxAmount, uint256 sweepAmount) external nonReentrant onlyBorrower { address self = address(this); if(sweep.isMintingAllowed()){ _borrow(sweepAmount); } else { TransferHelper.safeTransferFrom(address(sweep), msg.sender, self, sweepAmount); } 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[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, uint256 slippage) internal { address self = address(this); 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, uint256 slippage) external nonReentrant onlyBorrower { address self = address(this); if(sweep.isMintingAllowed()){ uint256 sweepLimit = sweep.minters(address(this)).maxAmount; uint256 sweepAvailable = sweepLimit - sweepBorrowed; if (sweepAvailable < sweepAmount) revert NotEnoughBalance(); if(sweepAmount > 0) _borrow(sweepAmount); } else { TransferHelper.safeTransferFrom(address(sweep), msg.sender, self, sweepAmount); } TransferHelper.safeTransferFrom(address(usdx), msg.sender, self, usdxAmount); TransferHelper.safeApprove(address(usdx), address(vault), usdxAmount); TransferHelper.safeApprove(address(sweep), address(vault), sweepAmount); _addLiquidity(usdxAmount, sweepAmount, slippage); emit LiquidityAdded(usdxAmount, sweepAmount); } function removeLiquidity(uint256 usdxAmount, uint256 sweepAmount, uint256 slippage) 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 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(asset); } }
// 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) { return _calculateEquityRatio(0, 0); } /** * @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 virtual returns (uint256) { (uint256 usdxBalance, uint256 sweepBalance) = _balances(); uint256 sweepInUsd = sweep.convertToUSD(sweepBalance); uint256 usdxInUsd = _oracleUsdxToUsd(usdxBalance); return usdxInUsd + sweepInUsd; } /** * @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 ) external onlyBorrower whenNotPaused validAmount(sweepAmount) nonReentrant { if (!sweep.isValidMinter(address(this))) revert InvalidMinter(); uint256 sweepAvailable = loanLimit - sweepBorrowed; if (sweepAvailable < sweepAmount) revert NotEnoughBalance(); int256 currentEquityRatio = _calculateEquityRatio(sweepAmount, 0); if (currentEquityRatio < minEquityRatio) revert EquityRatioExcessed(); _borrow(sweepAmount); } /** * @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 price, uint256 slippage ) external nonReentrant { if (msg.sender != sweep.balancer()) revert NotBalancer(); (uint256 usdxBalance, uint256 sweepBalance) = _balances(); uint256 repayAmount = sweepAmount.min(sweepBorrowed); 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) { uint256 missingUsd = _oracleUsdxToUsd(missingUsdx); uint256 sweepInUsdx = missingUsd.mulDiv( 10 ** sweep.decimals(), price ); uint256 minAmountOut = OvnMath.subBasisPoints( sweepInUsdx, slippage ); _buy(missingUsdx, minAmountOut); } } 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 price. * @param slippage. */ function autoInvest( uint256 sweepAmount, uint256 price, uint256 slippage ) external nonReentrant { if (msg.sender != sweep.balancer()) revert NotBalancer(); uint256 sweepLimit = sweep.minters(address(this)).maxAmount; uint256 sweepAvailable = sweepLimit - sweepBorrowed; sweepAmount = sweepAmount.min(sweepAvailable); int256 currentEquityRatio = _calculateEquityRatio(sweepAmount, 0); if (!autoInvestEnabled) revert NotAutoInvest(); if (sweepAmount < autoInvestMinAmount) revert NotAutoInvestMinAmount(); if (currentEquityRatio < autoInvestMinRatio) revert NotAutoInvestMinRatio(); _borrow(sweepAmount); uint256 usdAmount = sweepAmount.mulDiv(price, 10 ** sweep.decimals()); uint256 usdInUsdx = _oracleUsdToUsdx(usdAmount); uint256 minAmountOut = OvnMath.subBasisPoints(usdInUsdx, slippage); uint256 usdxAmount = _sell(sweepAmount, minAmountOut); _invest(usdxAmount, 0, slippage); 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 amountOutMin Minimum amount out. * @dev Increases the sweep balance and decrease usdx balance. */ function buySweepOnAMM( uint256 usdxAmount, uint256 amountOutMin ) external onlyBorrower whenNotPaused nonReentrant returns (uint256 sweepAmount) { sweepAmount = _buy(usdxAmount, amountOutMin); emit Bought(sweepAmount); } /** * @notice Sell Sweep * Sells sweep amount from the stabilizer's balance to the AMM (swaps SWEEP to USDX). * @param sweepAmount. * @param amountOutMin Minimum amount out. * @dev Decreases the sweep balance and increase usdx balance */ function sellSweepOnAMM( uint256 sweepAmount, uint256 amountOutMin ) external onlyBorrower whenNotPaused nonReentrant returns (uint256 usdxAmount) { usdxAmount = _sell(sweepAmount, amountOutMin); 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 ) external onlyBorrower whenNotPaused validAmount(usdxAmount) nonReentrant { uint256 usdxInUsd = _oracleUsdxToUsd(usdxAmount); uint256 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 ) external onlyBorrower whenNotPaused validAmount(sweepAmount) nonReentrant { uint256 sweepInUsd = sweep.convertToUSD(sweepAmount); uint256 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); } /** * @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 { if (amount > IERC20Metadata(token).balanceOf(address(this))) revert NotEnoughBalance(); if (sweepBorrowed > 0) { if (token != address(sweep) && token != address(usdx)) revert InvalidToken(); uint256 usdAmount = token == address(sweep) ? sweep.convertToUSD(amount) : _oracleUsdxToUsd(amount); int256 currentEquityRatio = _calculateEquityRatio(0, usdAmount); if (currentEquityRatio < minEquityRatio) revert EquityRatioExcessed(); } TransferHelper.safeTransfer(token, msg.sender, amount); emit Withdrawn(token, amount); } /** * @notice Start auction * Initiates a dutch auction for liquidation. */ function startAuction() external { 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 ========== */ /** * @notice Invest To Asset. */ function _invest(uint256, uint256, uint256) internal virtual {} /** * @notice Divest From Asset. */ function _divest(uint256, uint256) internal virtual returns (uint256) {} /** * @notice Get asset address to liquidate. */ function _getToken() internal 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 amountOutMin ) internal returns (uint256) { uint256 usdxBalance = usdx.balanceOf(address(this)); usdxAmount = usdxAmount.min(usdxBalance); if (usdxAmount == 0) revert NotEnoughBalance(); IAMM _amm = amm(); TransferHelper.safeApprove(address(usdx), address(_amm), usdxAmount); uint256 sweepAmount = _amm.buySweep( address(usdx), usdxAmount, amountOutMin ); return sweepAmount; } function _sell( uint256 sweepAmount, uint256 amountOutMin ) internal returns (uint256) { uint256 sweepBalance = sweep.balanceOf(address(this)); sweepAmount = sweepAmount.min(sweepBalance); if (sweepAmount == 0) revert NotEnoughBalance(); IAMM _amm = amm(); TransferHelper.safeApprove(address(sweep), address(_amm), sweepAmount); uint256 usdxAmount = _amm.sellSweep( address(usdx), sweepAmount, amountOutMin ); return usdxAmount; } function _borrow(uint256 sweepAmount) internal { 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 Calculate Equity Ratio * Calculated the equity ratio based on the internal storage. * @param sweepDelta Variation of SWEEP to recalculate the new equity ratio. * @param usdDelta Variation of USD to recalculate the new equity ratio. * @return the new equity ratio used to control the Mint and Withdraw functions. * @dev Current Equity Ratio percentage has a precision of 4 decimals. */ function _calculateEquityRatio( uint256 sweepDelta, uint256 usdDelta ) internal view returns (int256) { uint256 currentValue_ = currentValue(); uint256 sweepDeltaInUsd = sweep.convertToUSD(sweepDelta); uint256 totalValue = currentValue_ + sweepDeltaInUsd - usdDelta; if (totalValue == 0) { if (sweepBorrowed > 0) return -1e6; else return 0; } uint256 seniorTrancheInUsd = sweep.convertToUSD( sweepBorrowed + sweepDelta ); // 1e6 is decimals of the percentage result int256 currentEquityRatio = ((int256(totalValue) - int256(seniorTrancheInUsd)) * 1e6) / int256(totalValue); if (currentEquityRatio < -1e6) currentEquityRatio = -1e6; return currentEquityRatio; } /** * @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":[{"internalType":"address","name":"asset","type":"address"}],"name":"BadAddress","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"},{"internalType":"uint256","name":"slippage","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":"price","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":"price","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":"sweepAmount","type":"uint256"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"buySweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","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":"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":[],"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"},{"internalType":"uint256","name":"slippage","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":"amountOutMin","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":[],"name":"settingsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdxAmount","type":"uint256"}],"name":"swapUsdxToSweep","outputs":[],"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
60a06040523480156200001157600080fd5b50604051620064f6380380620064f68339810160408190526200003491620005d3565b8585858584836001600160a01b0381166200006257604051632887dd7560e11b815260040160405180910390fd5b6001600160a01b039081166080526000805460ff191690556001805581166200009e57604051632887dd7560e11b815260040160405180910390fd5b6004620000ac868262000774565b50600280546001600160a01b03199081166001600160a01b039586161790915560038054821693851693909317909255600580549092169083161790556011805461010061ff0019909116811790915560168054610100600160a81b03191687841683021790819055604080516311b2515f60e31b81529051929091049092169350638d928af8925060048083019260209291908290030181865afa1580156200015a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000180919062000840565b601780546001600160a01b0319166001600160a01b039283161790556016546040805163038fff2d60e41b81529051610100909204909216916338fff2d09160048083019260209291908290030181865afa158015620001e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200020a919062000867565b6018819055601754604051631f29a8cd60e31b815260048101929092526001600160a01b03169063f94d466890602401600060405180830381865afa15801562000258573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200028291908101906200091a565b5050805162000299906019906020840190620004de565b5050620003066080516019805480602002602001604051908101604052809291908181526020018280548015620002fa57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311620002db575b50506200044892505050565b601a805460ff191660ff9290921691909117905560025460198054604080516020808402820181019092528281526200038c946001600160a01b03169390929091830182828015620002fa576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311620002db5750506200044892505050565b601a60016101000a81548160ff021916908360ff16021790555062000422601660019054906101000a90046001600160a01b03166019805480602002602001604051908101604052809291908181526020018280548015620002fa576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311620002db5750506200044892505050565b601a60026101000a81548160ff021916908360ff16021790555050505050505062000a39565b6000805b82518160ff161015620004af57836001600160a01b0316838260ff16815181106200047b576200047b620009f5565b60200260200101516001600160a01b0316036200049a579050620004d8565b80620004a68162000a0b565b9150506200044c565b50604051637833514560e11b81526001600160a01b038416600482015260240160405180910390fd5b92915050565b82805482825590600052602060002090810192821562000536579160200282015b828111156200053657825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620004ff565b506200054492915062000548565b5090565b5b8082111562000544576000815560010162000549565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620005a057620005a06200055f565b604052919050565b6001600160a01b0381168114620005be57600080fd5b50565b8051620005ce81620005a8565b919050565b60008060008060008060c08789031215620005ed57600080fd5b86516001600160401b03808211156200060557600080fd5b818901915089601f8301126200061a57600080fd5b8151818111156200062f576200062f6200055f565b6020915062000647601f8201601f1916830162000575565b8181528b838386010111156200065c57600080fd5b60005b828110156200067c5784810184015182820185015283016200065f565b506000838383010152809950505062000697818a01620005c1565b96505050620006a960408801620005c1565b9350620006b960608801620005c1565b9250620006c960808801620005c1565b9150620006d960a08801620005c1565b90509295509295509295565b600181811c90821680620006fa57607f821691505b6020821081036200071b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200076f57600081815260208120601f850160051c810160208610156200074a5750805b601f850160051c820191505b818110156200076b5782815560010162000756565b5050505b505050565b81516001600160401b038111156200079057620007906200055f565b620007a881620007a18454620006e5565b8462000721565b602080601f831160018114620007e05760008415620007c75750858301515b600019600386901b1c1916600185901b1785556200076b565b600085815260208120601f198616915b828110156200081157888601518255948401946001909101908401620007f0565b5085821015620008305787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156200085357600080fd5b81516200086081620005a8565b9392505050565b6000602082840312156200087a57600080fd5b5051919050565b60006001600160401b038211156200089d576200089d6200055f565b5060051b60200190565b600082601f830112620008b957600080fd5b81516020620008d2620008cc8362000881565b62000575565b82815260059290921b84018101918181019086841115620008f257600080fd5b8286015b848110156200090f5780518352918301918301620008f6565b509695505050505050565b6000806000606084860312156200093057600080fd5b83516001600160401b03808211156200094857600080fd5b818601915086601f8301126200095d57600080fd5b8151602062000970620008cc8362000881565b82815260059290921b8401810191818101908a8411156200099057600080fd5b948201945b83861015620009bb578551620009ab81620005a8565b8252948201949082019062000995565b91890151919750909350505080821115620009d557600080fd5b50620009e486828701620008a7565b925050604084015190509250925092565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff810362000a3057634e487b7160e01b600052601160045260246000fd5b60010192915050565b6080516158e862000c0e6000396000818161054d015281816107b701528181610863015281816108f80152818161099c01528181610a7c01528181610ace01528181610c8201528181610d1001528181610dbb01528181610e4301528181610f8d0152818161102d0152818161104e015281816111180152818161118d0152818161120f01528181611322015281816113c00152818161149301528181611530015281816115f70152818161165c015281816116e0015281816118400152818161199701528181611a4f01528181611b1801528181611c3901528181611d3401528181611dd201528181611fab01528181612050015281816123a20152818161243a0152818161249f01528181612a1901528181612b4901528181612c6101528181612d2f01528181612e780152818161310301528181613173015281816131ce01528181613358015281816134720152818161380701528181613891015281816138b201528181613bb901528181613c5e015281816140690152818161419b015281816141bc0152818161421d01528181614259015281816144d7015281816145ab0152818161466001528181614834015281816148df01528181614ab001528181614b2a0152614c4101526158e86000f3fe608060405234801561001057600080fd5b50600436106103d05760003560e01c80636b64c769116101ff578063bb3521201161011a578063de839ba4116100ad578063f69aa3d51161007c578063f69aa3d514610745578063f95c1b2614610758578063fa45d56214610765578063fbfa77cf1461077857600080fd5b8063de839ba41461070d578063ea8364aa14610716578063f3fef3a314610729578063f686138d1461073c57600080fd5b8063c5ebeaec116100e9578063c5ebeaec146106e0578063c6beb586146106f3578063d366a41f146106fc578063d6fbf2021461070457600080fd5b8063bb352120146106aa578063bc5477ad146106b3578063c0f4a005146106c6578063c198f8ba146106d857600080fd5b8063a195166511610192578063a71891c311610161578063a71891c31461067f578063ad81fced14610687578063b220a79b14610690578063ba2d0344146106a257600080fd5b8063a19516651461065d578063a38aaa9014610666578063a516ed021461066e578063a6a8f1f91461067657600080fd5b80638456cb59116101ce5780638456cb591461061c578063857620e1146106245780638d1d7c61146106375780639e1b00451461064a57600080fd5b80636b64c769146105e6578063717e794d146105ee5780637df1f1b9146105f65780638351faf51461060957600080fd5b806329b154c3116102ef5780633e0dc34e116102825780634dc415de116102515780634dc415de146105b85780635c975abb146105c057806361ab077f146105cb578063698996f8146105de57600080fd5b80633e0dc34e1461058b5780633f4ba83a14610594578063422f10431461059c57806348dcacab146105af57600080fd5b80633168b03f116102be5780633168b03f1461053557806335faa41614610548578063371fd8e61461056f57806339518b5e1461058257600080fd5b806329b154c3146104fe5780632a943945146105115780632d76643c14610519578063311176d71461052257600080fd5b806314a6bf0f11610367578063234439441161033657806323443944146104be57806325d9b792146104c657806329610252146104d95780632982db00146104e157600080fd5b806314a6bf0f1461047557806316f0115b1461047d5780631c4695f4146104ad5780631de01bc9146104b557600080fd5b80630f5e07c7116103a35780630f5e07c71461044357806312bec0021461044c57806312f21a1a146104595780631370720f1461046257600080fd5b8063050d6f78146103d557806306fdde03146103ea5780630a246871146104085780630e5f5dbd1461042d575b600080fd5b6103e86103e3366004614f51565b61078b565b005b6103f2610b38565b6040516103ff9190614fc3565b60405180910390f35b601a5461041b9062010000900460ff1681565b60405160ff90911681526020016103ff565b610435610bc6565b6040519081526020016103ff565b61043560095481565b601a5461041b9060ff1681565b610435600d5481565b6103e8610470366004614fd6565b610c31565b610435610e18565b6016546104959061010090046001600160a01b031681565b6040516001600160a01b0390911681526020016103ff565b6103f2610e34565b610435600a5481565b6103e8610e41565b6104956104d4366004614fd6565b610f2a565b6103e8610f54565b6016546104ee9060ff1681565b60405190151581526020016103ff565b6103e861050c366004614fd6565b61110d565b610495611189565b61043560075481565b600254610495906001600160a01b031681565b6103e8610543366004614fd6565b61120d565b6104957f000000000000000000000000000000000000000000000000000000000000000081565b6103e861057d366004614fd6565b6112fb565b61043560125481565b61043560185481565b6103e8611320565b6103e86105aa366004614fef565b61147c565b610435600b5481565b6103e86116de565b60005460ff166104ee565b6104356105d9366004614f51565b6117da565b61043561183b565b6103e86118fb565b610435611992565b600554610495906001600160a01b031681565b6103e8610617366004614fef565b611a45565b6103e8611d32565b6103e8610632366004614fef565b611e8e565b600354610495906001600160a01b031681565b6103e8610658366004614f51565b61238b565b61043560105481565b6104ee612693565b6103e86126d9565b61043560155481565b61043561271c565b61043560085481565b601a5461041b90610100900460ff1681565b610435612950565b61043560145481565b6103e86106c1366004614fef565b612a0f565b6011546104ee90610100900460ff1681565b6103e8612df4565b6103e86106ee366004614fd6565b612e41565b61043560065481565b610435612f83565b61043560135481565b610435600c5481565b6103e8610724366004615072565b612f90565b6103e861073736600461514e565b61304f565b610435600f5481565b610435610753366004614f51565b6132c2565b6011546104ee9060ff1681565b6103e8610773366004614fd6565b61331d565b601754610495906001600160a01b031681565b6107936134e7565b600754604051633d1bb33160e21b8152306004820152600091906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f46eccc4906024016080604051808303816000875af1158015610800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108249190615190565b5161082f919061521b565b905061083c83600261522e565b81101561085c5760405163569d45cf60e11b815260040160405180910390fd5b60006108e87f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663dc38679c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e39190615245565b613545565b90506000620f424062ffffff16827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e19538476040518163ffffffff1660e01b8152600401602060405180830381865afa158015610954573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109789190615245565b610982919061522e565b61098c9190615274565b6109969083615288565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109f8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1c919061529b565b610a2790600a6153a2565b610a31838861522e565b610a3b9190615274565b600254909150610a56906001600160a01b03163330846135da565b600254601754610a73916001600160a01b039081169116836136e4565b601754610aab907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b0316886136e4565b610abe610ab987600261522e565b6137e4565b610ac9818787613993565b610af47f00000000000000000000000000000000000000000000000000000000000000003388613e38565b6040518181527f6e19477745f02fa64cb79e709afd8b6a5da159ef7b135546eafd67c38e425c439060200160405180910390a150505050610b3460018055565b5050565b60048054610b45906153b1565b80601f0160208091040260200160405190810160405280929190818152602001828054610b71906153b1565b8015610bbe5780601f10610b9357610100808354040283529160200191610bbe565b820191906000526020600020905b815481529060010190602001808311610ba157829003601f168201915b505050505081565b60075460009015610c2b57600062015180600d5442610be5919061521b565b610bef9190615274565b9050610c00620f424061016d61522e565b81600c54600754610c11919061522e565b610c1b919061522e565b610c259190615274565b91505090565b50600090565b610c39613f31565b610c41613f5c565b80610c4b81613fa2565b610c536134e7565b6000610c5e83613fc3565b604051633068b6b560e21b8152600481018290529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c1a2dad490602401602060405180830381865afa158015610cc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ced9190615245565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610d57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7b9190615245565b905080821115610d9e5760405163569d45cf60e11b815260040160405180910390fd5b600254610db6906001600160a01b03163330886135da565b610de17f00000000000000000000000000000000000000000000000000000000000000003384613e38565b60405182907fbc87b68cd9f40bbab98db9b9e4d393c4ef32d4660271a908b81cfa10d8a59df990600090a2505050610b3460018055565b6000610e22610bc6565b600754610e2f9190615288565b905090565b600e8054610b45906153b1565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ec391906153eb565b6001600160a01b0316336001600160a01b031614610ef45760405163698bba4b60e01b815260040160405180910390fd5b6000600b81905560098190556040517f219124ae95cc25cf220d998f2867d37fb4ab4908cce7c51adfa33ce747aa5747908290a2565b60198181548110610f3a57600080fd5b6000918252602090912001546001600160a01b0316905081565b610f5c613f31565b610f646134e7565b6000610f6e610bc6565b42600d556040516370a0823160e01b81523060048201529091506000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610fdc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110009190615245565b905080821115611022576040516206230160eb1b815260040160405180910390fd5b8115611100576110d47f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166361d027b36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ce91906153eb565b84613e38565b60405182907fda0ff68ccd5fb797a8f86207386ea961ca6990c15ace2424ab51eb871ed4959990600090a25b505061110b60018055565b565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146111565760405163bc9eca6160e01b815260040160405180910390fd5b600781905560405181907f35ba42ee3c2daa6cf14836eefff16b184565798767ec1e5d723008848aeaf7e390600090a250565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632a9439456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111e9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e2f91906153eb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128f91906153eb565b6001600160a01b0316336001600160a01b0316146112c05760405163698bba4b60e01b815260040160405180910390fd5b60088190556040518181527f7760d892a7883522367f0eaea35e968381a018418c249cd9aaaca190fe5d88179060200160405180910390a150565b611303613f31565b61130b6134e7565b61131481614051565b61131d60018055565b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663baf4a3126040518163ffffffff1660e01b8152600401602060405180830381865afa15801561137e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a291906153eb565b6001600160a01b0316336001600160a01b03161415801561145657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561141c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144091906153eb565b6001600160a01b0316336001600160a01b031614155b1561147457604051631e1c735b60e21b815260040160405180910390fd5b61110b614303565b6114846134e7565b61148c613f31565b60003090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632b4818836040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115139190615408565b156115f257604051633d1bb33160e21b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f46eccc4906024016080604051808303816000875af1158015611581573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a59190615190565b516007549091506000906115b9908361521b565b9050848110156115dc5760405163569d45cf60e11b815260040160405180910390fd5b84156115eb576115eb856137e4565b505061161e565b61161e7f00000000000000000000000000000000000000000000000000000000000000003383866135da565b600254611636906001600160a01b03163383876135da565b600254601754611653916001600160a01b039081169116866136e4565b60175461168b907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b0316856136e4565b611696848484613993565b60408051858152602081018590527f38f8a0c92f4c5b0b6877f878cb4c0c8d348a47b76d716c8e78f425043df9515b910160405180910390a1506116d960018055565b505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561173c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176091906153eb565b6001600160a01b0316336001600160a01b03161461179157604051632d5be4cb60e21b815260040160405180910390fd5b6011805461ff0019166101001790556005546040516001600160a01b03909116907faf77f8960cf590e245ec8b6d41c193a5dcacad8986ae4eb57ac9e5be7b6af03190600090a2565b60006117e4613f31565b6117ec613f5c565b6117f46134e7565b6117fe8383614355565b60405190915081907f4e08ba899977cf7d4c2964bce71c6b9a7ef76ee5166a4c1249a1e08016e33ef190600090a261183560018055565b92915050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389da7df8611875610bc6565b6040518263ffffffff1660e01b815260040161189391815260200190565b602060405180830381865afa1580156118b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d49190615245565b9050806118df6144a4565b6118e761271c565b6118f19190615288565b610c25919061521b565b611903612693565b6119205760405163038cbd4b60e31b815260040160405180910390fd5b60165460ff16158061193457506000601354115b156119525760405163829e373360e01b815260040160405180910390fd5b4260125560065460009061196990620f424061521b565b905080620f4240611978610e18565b611982919061522e565b61198c9190615274565b60135550565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389da7df86007546040518263ffffffff1660e01b81526004016119e591815260200190565b602060405180830381865afa158015611a02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a269190615245565b90506000611a3261183b565b9050611a3e8282615425565b9250505090565b611a4d6134e7565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611aab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611acf91906153eb565b6001600160a01b0316336001600160a01b031614611b005760405163698bba4b60e01b815260040160405180910390fd5b604051633d1bb33160e21b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f46eccc4906024016080604051808303816000875af1158015611b69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b8d9190615190565b51600754909150600090611ba1908361521b565b9050611bad8582614564565b94506000611bbc86600061457c565b60115490915060ff16611be2576040516305b02a1960e01b815260040160405180910390fd5b601054861015611c05576040516312cd610d60e21b815260040160405180910390fd5b600f54811215611c28576040516378764b0f60e01b815260040160405180910390fd5b611c31866137e4565b6000611ccc867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb9919061529b565b611cc490600a6153a2565b899190614740565b90506000611cd982613545565b90506000611ce782886147ee565b90506000611cf58a83614812565b90506040518a907f8f77e6a87a8210bff9857b08990b1f360b73d6e92d422a9a0e2c78e449682a9c90600090a2505050505050506116d960018055565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663baf4a3126040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db491906153eb565b6001600160a01b0316336001600160a01b031614158015611e6857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e5291906153eb565b6001600160a01b0316336001600160a01b031614155b15611e8657604051631e1c735b60e21b815260040160405180910390fd5b61110b614947565b611e966134e7565b611e9e613f31565b6002546040805163313ce56760e01b8152905130926000926001600160a01b039091169163313ce567916004808201926020929091908290030181865afa158015611eed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f11919061529b565b611f1c90600a6153a2565b601654600254604051632a6f500560e11b81526001600160a01b03918216600482015261010090920416906354dea00a90602401602060405180830381865afa158015611f6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f919190615245565b611f9b908761522e565b611fa59190615274565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612007573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202b919061529b565b61203690600a6153a2565b601654604051632a6f500560e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152610100909204909116906354dea00a90602401602060405180830381865afa1580156120a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ca9190615245565b6120d4908761522e565b6120de9190615274565b90506000620f42406120f08682615288565b6120fa8486615288565b612104919061522e565b61210e9190615274565b60408051600380825260808201909252919250600091906020820160608036833701905050601a54815191925089918391610100900460ff169081106121565761215661544c565b6020908102919091010152601a5481518891839160ff90911690811061217e5761217e61544c565b60209081029190910101526040805160028082526060820190925260009181602001602082028036833701905050601a5490915060ff610100820481169116116121c857876121ca565b885b816000815181106121dd576121dd61544c565b6020908102919091010152601a5460ff610100820481169116116122015788612203565b875b816001815181106122165761221661544c565b60200260200101818152505060006001828560405160200161223a939291906154b3565b60408051601f198184030181526019805460a06020820286018101909452608085018181529295506000949384939291908401828280156122a457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612286575b505050918352505060208101869052604080820185905260006060909201919091526017546018549151638bdb391360e01b81529293506001600160a01b031691638bdb3913916122fd918c9081908790600401615583565b600060405180830381600087803b15801561231757600080fd5b505af115801561232b573d6000803e3d6000fd5b5050505060008a1115612341576123418a614051565b604080518c8152602081018c90527f6f0f96292ae0038c04f9b6bab30f185d9ca02c471d0983f563f2a4f674aef137910160405180910390a150505050505050506116d960018055565b6123936134e7565b61239b613f31565b60003090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632b4818836040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124229190615408565b1561243557612430826137e4565b612461565b6124617f00000000000000000000000000000000000000000000000000000000000000003383856135da565b600254612479906001600160a01b03163383866135da565b600254601754612496916001600160a01b039081169116856136e4565b6017546124ce907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b0316846136e4565b604080516003808252608082019092526000916020820160608036833701905050601a548151919250600160701b91839162010000900460ff169081106125175761251761544c565b6020026020010181815250508381601a60019054906101000a900460ff1660ff16815181106125485761254861544c565b6020908102919091010152601a5481518491839160ff9091169081106125705761257061544c565b602002602001018181525050600080826040516020016125919291906155c9565b60408051601f198184030181526019805460a06020820286018101909452608085018181529295506000949384939291908401828280156125fb57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116125dd575b50505091835250506020810185905260408082018590526000606090920191909152601754601854915163172b958560e31b81529293506001600160a01b03169163b95cac289161265491889081908790600401615583565b600060405180830381600087803b15801561266e57600080fd5b505af1158015612682573d6000803e3d6000fd5b5050505050505050610b3460018055565b600080600a541180156126a857506000600b54115b80156126b5575060095442115b80610e2f57506000600754118015610e2f57506006546126d3612f83565b12905090565b6126e16134e7565b601254600003612704576040516334dc687f60e11b815260040160405180910390fd5b600061270e612950565b905060006111008183614984565b6016546040516370a0823160e01b815230600482015260009182916101009091046001600160a01b0316906370a0823190602401602060405180830381865afa15801561276d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127919190615245565b90506000601660019054906101000a90046001600160a01b03166001600160a01b031663679aefce6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280c9190615245565b90506000601660019054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612863573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612887919061529b565b6128929060026155f1565b61289d90600a6153a2565b600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612914919061529b565b61291f90600a6153a2565b612929848661522e565b612933919061522e565b61293d9190615274565b905061294881613fc3565b935050505090565b600080620f4240601554620f4240612968919061521b565b600754612975919061522e565b61297f9190615274565b9050600061012c60125442612994919061521b565b61299e9190615274565b90506000601454826129b0919061522e565b9050620f42408111156129c557509092915050565b60006129d482620f424061521b565b90506000620f4240826013546129ea919061522e565b6129f49190615274565b9050808511612a035780612a05565b845b9550505050505090565b612a176134e7565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e563037e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a9991906153eb565b6001600160a01b0316336001600160a01b031614612aca5760405163698bba4b60e01b815260040160405180910390fd5b600080612ad5614bb8565b915091506000612af06007548761456490919063ffffffff16565b600a5490915015612b1157600a54612b089042615288565b600955600b8190555b80821015612d17576000612b25838361521b565b60405163113b4fbf60e31b8152600481018290529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906389da7df890602401602060405180830381865afa158015612b90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bb49190615245565b90506000612bc182613545565b905085811115612bda57612bd8610c2b878361521b565b505b6002546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612c23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c479190615245565b1115612d13576000612c5882613fc3565b90506000612cf47f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce1919061529b565b612cec90600a6153a2565b83908c614740565b90506000612d02828b6147ee565b9050612d0e8482614355565b505050505b5050505b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612d7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da29190615245565b118015612daf5750600081115b15612dbd57612dbd81614051565b60405186907fdfcd68ceed46252749a4089f344aec4b4ee7f28a068f704c21799355325f3da990600090a25050506116d960018055565b612dfc613f31565b6011805461ff00191690556005546040516001600160a01b03909116907facf29ad8d63913d38e7e1176963a4afb76bf0918516051da68408ecb6f98065d90600090a2565b612e49613f31565b612e51613f5c565b80612e5b81613fa2565b612e636134e7565b60405163b67e9df760e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b67e9df790602401602060405180830381865afa158015612ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eeb9190615408565b612f085760405163d8d5894f60e01b815260040160405180910390fd5b6000600754600854612f1a919061521b565b905082811015612f3d5760405163569d45cf60e11b815260040160405180910390fd5b6000612f4a84600061457c565b9050600654811215612f6f5760405163374c72ff60e11b815260040160405180910390fd5b612f78846137e4565b5050610b3460018055565b6000610e2f60008061457c565b612f98613f31565b612fa0614cba565b60068c9055600c8b905560088a90556014899055600a889055600f879055601086905560158590556011805460ff199081168615151790915560168054909116841515179055600e612ff3828483615653565b508a8c7fed1352796b02006c8bf7ef68956cb9fc55c08f9193eee9cec7ee590840bbbaad8c6014548c8c8c8c8c8c8c8c6040516130399a99989796959493929190615713565b60405180910390a3505050505050505050505050565b613057613f31565b61305f613f5c565b8061306981613fa2565b6130716134e7565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa1580156130b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130d99190615245565b8211156130f95760405163569d45cf60e11b815260040160405180910390fd5b60075415613278577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161415801561315157506002546001600160a01b03848116911614155b1561316f5760405163c1ab6dc160e01b815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316146131b8576131b383613fc3565b613241565b60405163113b4fbf60e31b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906389da7df890602401602060405180830381865afa15801561321d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132419190615245565b9050600061325060008361457c565b90506006548112156132755760405163374c72ff60e11b815260040160405180910390fd5b50505b613283833384613e38565b60405182906001600160a01b038516907f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d590600090a36116d960018055565b60006132cc613f31565b6132d4613f5c565b6132dc6134e7565b6132e68383614812565b60405190915083907f92f64ca637d023f354075a4be751b169c1a8a9ccb6d33cdd0cb352054399572790600090a261183560018055565b613325613f31565b61332d613f5c565b8061333781613fa2565b61333f6134e7565b60405163113b4fbf60e31b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906389da7df890602401602060405180830381865afa1580156133a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cb9190615245565b905060006133d882613545565b6002546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015613426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061344a9190615245565b90508082111561346d5760405163569d45cf60e11b815260040160405180910390fd5b6134997f00000000000000000000000000000000000000000000000000000000000000003330886135da565b6002546134b0906001600160a01b03163384613e38565b60405182907fdcadafc28aac48a048c875f5f3127f2189b02d21291b563568cf8892a596bbb090600090a2505050610b3460018055565b60026001540361353e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600155565b600061183582600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561359e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c2919061529b565b60035460ff91909116906001600160a01b0316614ce2565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b179052915160009283929088169161363e9190615784565b6000604051808303816000865af19150503d806000811461367b576040519150601f19603f3d011682016040523d82523d6000602084013e613680565b606091505b50915091508180156136aa5750805115806136aa5750808060200190518101906136aa9190615408565b6136dc5760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b6044820152606401613535565b505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916137409190615784565b6000604051808303816000865af19150503d806000811461377d576040519150601f19603f3d011682016040523d82523d6000602084013e613782565b606091505b50915091508180156137ac5750805115806137ac5750808060200190518101906137ac9190615408565b6137dd5760405162461bcd60e51b8152602060048201526002602482015261534160f01b6044820152606401613535565b5050505050565b60006137ee610bc6565b60405163140e25ad60e31b8152600481018490529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a0712d6890602401600060405180830381600087803b15801561385357600080fd5b505af1158015613867573d6000803e3d6000fd5b50505050816007600082825461387d9190615288565b909155505042600d558015613964576139387f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166361d027b36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561390e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061393291906153eb565b83613e38565b60405181907fda0ff68ccd5fb797a8f86207386ea961ca6990c15ace2424ab51eb871ed4959990600090a25b60405182907f69c0ed5a77051ba5f0c42418bb6db6d3f73884dea69811c50bf320298df6ca5c90600090a25050565b604080516003808252608082019092523091600091906020820160608036833701905050601a54815191925086918391610100900460ff169081106139da576139da61544c565b6020908102919091010152601a5481518591839160ff909116908110613a0257613a0261544c565b60209081029190910101526040805160028082526060820190925260009181602001602082028036833701905050601a5490915060ff61010082048116911611613a4c5784613a4e565b855b81600081518110613a6157613a6161544c565b6020908102919091010152601a5460ff61010082048116911611613a855785613a87565b845b81600181518110613a9a57613a9a61544c565b6020026020010181815250506000600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613afb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1f919061529b565b613b2a90600a6153a2565b601654600254604051632a6f500560e11b81526001600160a01b03918216600482015261010090920416906354dea00a90602401602060405180830381865afa158015613b7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b9f9190615245565b613ba9908961522e565b613bb39190615274565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613c15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c39919061529b565b613c4490600a6153a2565b601654604051632a6f500560e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152610100909204909116906354dea00a90602401602060405180830381865afa158015613cb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cd89190615245565b613ce2908961522e565b613cec9190615274565b90506000620f4240613cfe888261521b565b613d088486615288565b613d12919061522e565b613d1c9190615274565b9050600060018583604051602001613d36939291906157a0565b60408051601f198184030181526019805460a0602082028601810190945260808501818152929550600094938493929190840182828015613da057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613d82575b50505091835250506020810189905260408082018590526000606090920191909152601754601854915163172b958560e31b81529293506001600160a01b03169163b95cac2891613df9918c9081908790600401615583565b600060405180830381600087803b158015613e1357600080fd5b505af1158015613e27573d6000803e3d6000fd5b505050505050505050505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691613e949190615784565b6000604051808303816000865af19150503d8060008114613ed1576040519150601f19603f3d011682016040523d82523d6000602084013e613ed6565b606091505b5091509150818015613f00575080511580613f00575080806020019051810190613f009190615408565b6137dd5760405162461bcd60e51b815260206004820152600260248201526114d560f21b6044820152606401613535565b6005546001600160a01b0316331461110b57604051631963d1e760e31b815260040160405180910390fd5b60005460ff161561110b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401613535565b8060000361131d57604051639d635cff60e01b815260040160405180910390fd5b600061183582600260009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561401c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614040919061529b565b6003546001600160a01b0316614d3f565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156140b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140dc9190615245565b90506140e88282614564565b91508160000361410b5760405163569d45cf60e11b815260040160405180910390fd5b81600b541161411b576000614129565b81600b54614129919061521b565b600b55600a541580159061413d5750600b54155b156141485760006009555b6000614152610bc6565b42600d559050614162818461521b565b925082600754101561417e576007805460009091559250614196565b8260076000828254614190919061521b565b90915550505b6142187f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166361d027b36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561390e573d6000803e3d6000fd5b6142437f000000000000000000000000000000000000000000000000000000000000000030856136e4565b604051630852cd8d60e31b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342966c6890602401600060405180830381600087803b1580156142a557600080fd5b505af11580156142b9573d6000803e3d6000fd5b50506040518592507f33a382daad6aace935340a474d09fec82af4bec7e2b69518d283231b03a65f249150600090a26142f0612693565b6116d9576116d960006012819055601355565b61430b614d8f565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6002546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156143a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143c69190615245565b90506143d28482614564565b9350836000036143f55760405163569d45cf60e11b815260040160405180910390fd5b60006143ff611189565b600254909150614419906001600160a01b031682876136e4565b60025460405163231831c760e21b81526001600160a01b0391821660048201526024810187905260448101869052600091831690638c60c71c906064015b6020604051808303816000875af1158015614476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061449a9190615245565b9695505050505050565b60008060006144b1614bb8565b60405163113b4fbf60e31b81526004810182905291935091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906389da7df890602401602060405180830381865afa15801561451e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145429190615245565b9050600061454f84613fc3565b905061455b8282615288565b94505050505090565b60008183106145735781614575565b825b9392505050565b60008061458761183b565b60405163113b4fbf60e31b8152600481018690529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906389da7df890602401602060405180830381865afa1580156145f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146169190615245565b90506000846146258385615288565b61462f919061521b565b90508060000361465c576007541561465057620f423f199350505050611835565b60009350505050611835565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166389da7df88860075461469b9190615288565b6040518263ffffffff1660e01b81526004016146b991815260200190565b602060405180830381865afa1580156146d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146fa9190615245565b90506000826147098382615425565b61471690620f42406157c0565b61472091906157f0565b9050620f423f198112156147355750620f423f195b979650505050505050565b600080806000198587098587029250828110838203039150508060000361477a578382816147705761477061525e565b0492505050614575565b80841161478657600080fd5b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000620f42406147fe838261521b565b614808908561522e565b6145759190615274565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561487b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061489f9190615245565b90506148ab8482614564565b9350836000036148ce5760405163569d45cf60e11b815260040160405180910390fd5b60006148d8611189565b90506149057f000000000000000000000000000000000000000000000000000000000000000082876136e4565b600254604051631c6d209760e11b81526001600160a01b03918216600482015260248101879052604481018690526000918316906338da412e90606401614457565b61494f613f5c565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586143383390565b61498c612693565b6149a95760405163038cbd4b60e31b815260040160405180910390fd5b6002546040516370a0823160e01b81523060048201819052916000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156149f7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a1b9190615245565b6040516370a0823160e01b81526001600160a01b0384811660048301529192506000918616906370a0823190602401602060405180830381865afa158015614a67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a8b9190615245565b6040516370a0823160e01b81526001600160a01b0385811660048301529192506000917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015614af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b1b9190615245565b905080851115614b5a57614b5a7f00000000000000000000000000000000000000000000000000000000000000003386614b55858a61521b565b6135da565b600254614b71906001600160a01b03163385613e38565b614b7c863384613e38565b614b8585614051565b60405133907f1e1ef858062a7196d1891e397a5cde9891e6ddf61a81e9d269a3aaa7a95dacd890600090a2505050505050565b6002546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015614c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c299190615245565b6040516370a0823160e01b81523060048201529092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015614c90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cb49190615245565b90509091565b601154610100900460ff1661110b57604051634e751a9560e11b815260040160405180910390fd5b600080614cee83614dd8565b90506000614cfb84614e3c565b9050614d096006600a6153a2565b614d13908261522e565b614d208660ff8516615288565b614d2b90600a61581e565b614d35908861522e565b61449a9190615274565b600080614d4b83614dd8565b90506000614d5884614e3c565b9050614d64858361582a565b614d6f90600a6153a2565b614d7b6006600a6153a2565b614d85838961522e565b614d35919061522e565b60005460ff1661110b5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401613535565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015614e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611835919061529b565b6000806000806000856001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015614e82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ea69190615862565b9450945050935093508369ffffffffffffffffffff168169ffffffffffffffffffff161015614f025760405162461bcd60e51b81526020600482015260086024820152674f6c64206461746160c01b6044820152606401613535565b60008211614f475760405162461bcd60e51b8152602060048201526012602482015271526f756e64206e6f7420636f6d706c65746560701b6044820152606401613535565b5090949350505050565b60008060408385031215614f6457600080fd5b50508035926020909101359150565b60005b83811015614f8e578181015183820152602001614f76565b50506000910152565b60008151808452614faf816020860160208601614f73565b601f01601f19169290920160200192915050565b6020815260006145756020830184614f97565b600060208284031215614fe857600080fd5b5035919050565b60008060006060848603121561500457600080fd5b505081359360208301359350604090920135919050565b801515811461131d57600080fd5b60008083601f84011261503b57600080fd5b50813567ffffffffffffffff81111561505357600080fd5b60208301915083602082850101111561506b57600080fd5b9250929050565b6000806000806000806000806000806000806101608d8f03121561509557600080fd5b8c359b5060208d01359a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d013594506150d86101008e013561501b565b6101008d013593506150ee6101208e013561501b565b6101208d0135925067ffffffffffffffff6101408e0135111561511057600080fd5b6151218e6101408f01358f01615029565b81935080925050509295989b509295989b509295989b565b6001600160a01b038116811461131d57600080fd5b6000806040838503121561516157600080fd5b823561516c81615139565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b6000608082840312156151a257600080fd5b6040516080810181811067ffffffffffffffff821117156151c5576151c561517a565b8060405250825181526020830151602082015260408301516151e68161501b565b604082015260608301516151f98161501b565b60608201529392505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561183557611835615205565b808202811582820484141761183557611835615205565b60006020828403121561525757600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b6000826152835761528361525e565b500490565b8082018082111561183557611835615205565b6000602082840312156152ad57600080fd5b815160ff8116811461457557600080fd5b600181815b808511156152f95781600019048211156152df576152df615205565b808516156152ec57918102915b93841c93908002906152c3565b509250929050565b60008261531057506001611835565b8161531d57506000611835565b8160018114615333576002811461533d57615359565b6001915050611835565b60ff84111561534e5761534e615205565b50506001821b611835565b5060208310610133831016604e8410600b841016171561537c575081810a611835565b61538683836152be565b806000190482111561539a5761539a615205565b029392505050565b600061457560ff841683615301565b600181811c908216806153c557607f821691505b6020821081036153e557634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156153fd57600080fd5b815161457581615139565b60006020828403121561541a57600080fd5b81516145758161501b565b818103600083128015838313168383128216171561544557615445615205565b5092915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b600081518084526020808501945080840160005b838110156154a85781518752958201959082019060010161548c565b509495945050505050565b6000600385106154c5576154c5615462565b848252606060208301526154dc6060830185615478565b9050826040830152949350505050565b8051608080845281519084018190526000916020919082019060a0860190845b818110156155315783516001600160a01b03168352928401929184019160010161550c565b50508285015191508581038387015261554a8183615478565b92505050604083015184820360408601526155658282614f97565b915050606083015161557b606086018215159052565b509392505050565b8481526001600160a01b0384811660208301528316604082015260806060820181905260009061449a908301846154ec565b600481106155c5576155c5615462565b9052565b6155d381846155b5565b6040602082015260006155e96040830184615478565b949350505050565b60ff818116838216029081169081811461544557615445615205565b601f8211156116d957600081815260208120601f850160051c810160208610156156345750805b601f850160051c820191505b818110156136dc57828155600101615640565b67ffffffffffffffff83111561566b5761566b61517a565b61567f8361567983546153b1565b8361560d565b6000601f8411600181146156b3576000851561569b5750838201355b600019600387901b1c1916600186901b1783556137dd565b600083815260209020601f19861690835b828110156156e457868501358255602094850194600190920191016156c4565b50868210156157015760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60006101208c83528b60208401528a60408401528960608401528860808401528760a084015286151560c084015285151560e0840152806101008401528381840152506101408385828501376000838501820152601f909301601f19169091019091019a9950505050505050505050565b60008251615796818460208701614f73565b9190910192915050565b6157aa81856155b5565b6060602082015260006154dc6060830185615478565b80820260008212600160ff1b841416156157dc576157dc615205565b818105831482151761183557611835615205565b6000826157ff576157ff61525e565b600160ff1b82146000198414161561581957615819615205565b500590565b60006145758383615301565b60ff818116838216019081111561183557611835615205565b805169ffffffffffffffffffff8116811461585d57600080fd5b919050565b600080600080600060a0868803121561587a57600080fd5b61588386615843565b94506020860151935060408601519250606086015191506158a660808701615843565b9050929550929590935056fea264697066735822122036dd9e7470219475513bedd465d9c9f75f829a107aff554b6ceb88bfc00acf7464736f6c6343000813003300000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d43574000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029130000000000000000000000007e860098f58bbfc8648a4311b374b1d669a2bc6b00000000000000000000000015d9d108437b17d1fa70392f9ed086306229ec91000000000000000000000000a8ec2d0b62b85e55f410c0c94c7dc45919ba7c0a000000000000000000000000000000000000000000000000000000000000001542616c616e636572204d61726b6574204d616b65720000000000000000000000
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d43574000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029130000000000000000000000007e860098f58bbfc8648a4311b374b1d669a2bc6b00000000000000000000000015d9d108437b17d1fa70392f9ed086306229ec91000000000000000000000000a8ec2d0b62b85e55f410c0c94c7dc45919ba7c0a000000000000000000000000000000000000000000000000000000000000001542616c616e636572204d61726b6574204d616b65720000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): Balancer Market Maker
Arg [1] : _sweep (address): 0xB88a5Ac00917a02d82c7cd6CEBd73E2852d43574
Arg [2] : _usdx (address): 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Arg [3] : _oracleUsdx (address): 0x7e860098F58bBFC8648a4311b374B1D669a2bc6B
Arg [4] : _poolAddress (address): 0x15D9D108437B17d1FA70392f9eD086306229ec91
Arg [5] : _borrower (address): 0xA8ec2d0b62b85E55f410C0C94C7dc45919ba7c0A
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [1] : 000000000000000000000000b88a5ac00917a02d82c7cd6cebd73e2852d43574
Arg [2] : 000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913
Arg [3] : 0000000000000000000000007e860098f58bbfc8648a4311b374b1d669a2bc6b
Arg [4] : 00000000000000000000000015d9d108437b17d1fa70392f9ed086306229ec91
Arg [5] : 000000000000000000000000a8ec2d0b62b85e55f410c0c94c7dc45919ba7c0a
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000015
Arg [7] : 42616c616e636572204d61726b6574204d616b65720000000000000000000000
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.