More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 135,675 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Perform Upkeep M... | 329328724 | 40 mins ago | IN | 0 ETH | 0.00000418 | ||||
Perform Upkeep M... | 329328722 | 40 mins ago | IN | 0 ETH | 0.00000418 | ||||
Perform Upkeep M... | 329328721 | 40 mins ago | IN | 0 ETH | 0.00000912 | ||||
Perform Upkeep M... | 329314303 | 1 hr ago | IN | 0 ETH | 0.0000029 | ||||
Perform Upkeep M... | 329314302 | 1 hr ago | IN | 0 ETH | 0.00000289 | ||||
Perform Upkeep M... | 329314302 | 1 hr ago | IN | 0 ETH | 0.00000924 | ||||
Perform Upkeep M... | 329299941 | 2 hrs ago | IN | 0 ETH | 0.00000478 | ||||
Perform Upkeep M... | 329299940 | 2 hrs ago | IN | 0 ETH | 0.00000479 | ||||
Perform Upkeep M... | 329299940 | 2 hrs ago | IN | 0 ETH | 0.00001112 | ||||
Perform Upkeep M... | 329285502 | 3 hrs ago | IN | 0 ETH | 0.00000427 | ||||
Perform Upkeep M... | 329285501 | 3 hrs ago | IN | 0 ETH | 0.00000427 | ||||
Perform Upkeep M... | 329285501 | 3 hrs ago | IN | 0 ETH | 0.00000918 | ||||
Perform Upkeep M... | 329271032 | 4 hrs ago | IN | 0 ETH | 0.0000035 | ||||
Perform Upkeep M... | 329271032 | 4 hrs ago | IN | 0 ETH | 0.00001282 | ||||
Perform Upkeep M... | 329271031 | 4 hrs ago | IN | 0 ETH | 0.00000349 | ||||
Perform Upkeep M... | 329256610 | 5 hrs ago | IN | 0 ETH | 0.00000301 | ||||
Perform Upkeep M... | 329256608 | 5 hrs ago | IN | 0 ETH | 0.00000301 | ||||
Perform Upkeep M... | 329256608 | 5 hrs ago | IN | 0 ETH | 0.00000794 | ||||
Perform Upkeep M... | 329242208 | 6 hrs ago | IN | 0 ETH | 0.00000405 | ||||
Perform Upkeep M... | 329242207 | 6 hrs ago | IN | 0 ETH | 0.00000897 | ||||
Perform Upkeep M... | 329242206 | 6 hrs ago | IN | 0 ETH | 0.00000405 | ||||
Perform Upkeep M... | 329227728 | 7 hrs ago | IN | 0 ETH | 0.00000412 | ||||
Perform Upkeep M... | 329227727 | 7 hrs ago | IN | 0 ETH | 0.00000902 | ||||
Perform Upkeep M... | 329227726 | 7 hrs ago | IN | 0 ETH | 0.00000412 | ||||
Perform Upkeep M... | 329213338 | 8 hrs ago | IN | 0 ETH | 0.00000641 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH | ||||
72080275 | 764 days ago | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
PoolKeeper
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: CC-BY-NC-ND-4.0 pragma solidity 0.8.7; import "../interfaces/IPoolKeeper.sol"; import "../interfaces/IOracleWrapper.sol"; import "../interfaces/IPoolFactory.sol"; import "../interfaces/ILeveragedPool.sol"; import "../interfaces/IERC20DecimalsWrapper.sol"; import "../interfaces/IERC20DecimalsWrapper.sol"; import "./PoolSwapLibrary.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/proxy/Clones.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "abdk-libraries-solidity/ABDKMathQuad.sol"; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol"; /// @title The manager contract for multiple markets and the pools in them contract PoolKeeper is IPoolKeeper, Ownable { /* Constants */ uint256 public constant BASE_TIP = 5; // 5% base tip uint256 public constant TIP_DELTA_PER_BLOCK = 5; // 5% increase per block uint256 public constant BLOCK_TIME = 13; /* in seconds */ uint256 public constant MAX_DECIMALS = 18; // #### Global variables /** * @notice Format: Pool address => last executionPrice */ mapping(address => int256) public executionPrice; IPoolFactory public factory; bytes16 constant fixedPoint = 0x403abc16d674ec800000000000000000; // 1 ether uint256 public gasPrice = 10 gwei; // #### Functions constructor(address _factory) { require(_factory != address(0), "Factory cannot be 0 address"); factory = IPoolFactory(_factory); } /** * @notice When a pool is created, this function is called by the factory to initiate price trackings * @param _poolAddress The address of the newly-created pools */ function newPool(address _poolAddress) external override onlyFactory { address oracleWrapper = ILeveragedPool(_poolAddress).oracleWrapper(); int256 firstPrice = IOracleWrapper(oracleWrapper).getPrice(); require(firstPrice > 0, "First price is non-positive"); int256 startingPrice = ABDKMathQuad.toInt(ABDKMathQuad.mul(ABDKMathQuad.fromInt(firstPrice), fixedPoint)); emit PoolAdded(_poolAddress, firstPrice); executionPrice[_poolAddress] = startingPrice; } // Keeper network /** * @notice Check if upkeep is required * @param _pool The address of the pool to upkeep * @return upkeepNeeded Whether or not upkeep is needed for this single pool */ function checkUpkeepSinglePool(address _pool) public view override returns (bool) { if (!factory.isValidPool(_pool)) { return false; } // The update interval has passed return ILeveragedPool(_pool).intervalPassed(); } /** * @notice Checks multiple pools if any of them need updating * @param _pools The array of pools to check * @return upkeepNeeded Whether or not at least one pool needs upkeeping */ function checkUpkeepMultiplePools(address[] calldata _pools) external view override returns (bool) { for (uint256 i = 0; i < _pools.length; i++) { if (checkUpkeepSinglePool(_pools[i])) { // One has been found that requires upkeeping return true; } } return false; } /** * @notice Called by keepers to perform an update on a single pool * @param _pool The pool code to perform the update for */ function performUpkeepSinglePool(address _pool) public override { uint256 startGas = gasleft(); // validate the pool, check that the interval time has passed if (!checkUpkeepSinglePool(_pool)) { return; } ILeveragedPool pool = ILeveragedPool(_pool); (int256 latestPrice, bytes memory data, uint256 savedPreviousUpdatedTimestamp, uint256 updateInterval) = pool .getUpkeepInformation(); // Start a new round // Get price in WAD format int256 lastExecutionPrice = executionPrice[_pool]; executionPrice[_pool] = latestPrice; // This allows us to still batch multiple calls to executePriceChange, even if some are invalid // Without reverting the entire transaction try pool.poolUpkeep(lastExecutionPrice, latestPrice) { // If poolUpkeep is successful, refund the keeper for their gas costs uint256 gasSpent = startGas - gasleft(); payKeeper(_pool, gasPrice, gasSpent, savedPreviousUpdatedTimestamp, updateInterval); emit UpkeepSuccessful(_pool, data, lastExecutionPrice, latestPrice); } catch Error(string memory reason) { // If poolUpkeep fails for any other reason, emit event emit PoolUpkeepError(_pool, reason); } } /** * @notice Called by keepers to perform an update on multiple pools * @param pools pool codes to perform the update for */ function performUpkeepMultiplePools(address[] calldata pools) external override { for (uint256 i = 0; i < pools.length; i++) { performUpkeepSinglePool(pools[i]); } } /** * @notice Pay keeper for upkeep * @param _pool Address of the given pool * @param _gasPrice Price of a single gas unit (in ETH) * @param _gasSpent Number of gas units spent * @param _savedPreviousUpdatedTimestamp Last timestamp when the pool's price execution happened * @param _updateInterval Pool interval of the given pool */ function payKeeper( address _pool, uint256 _gasPrice, uint256 _gasSpent, uint256 _savedPreviousUpdatedTimestamp, uint256 _updateInterval ) internal { uint256 reward = keeperReward(_pool, _gasPrice, _gasSpent, _savedPreviousUpdatedTimestamp, _updateInterval); if (ILeveragedPool(_pool).payKeeperFromBalances(msg.sender, reward)) { emit KeeperPaid(_pool, msg.sender, reward); } else { // Usually occurs if pool just started and does not have any funds emit KeeperPaymentError(_pool, msg.sender, reward); } } /** * @notice Payment keeper receives for performing upkeep on a given pool * @param _pool Address of the given pool * @param _gasPrice Price of a single gas unit (in ETH) * @param _gasSpent Number of gas units spent * @param _savedPreviousUpdatedTimestamp Last timestamp when the pool's price execution happened * @param _poolInterval Pool interval of the given pool * @return Number of settlement tokens to give to the keeper for work performed */ function keeperReward( address _pool, uint256 _gasPrice, uint256 _gasSpent, uint256 _savedPreviousUpdatedTimestamp, uint256 _poolInterval ) public view returns (uint256) { // keeper gas cost in wei. WAD formatted uint256 _keeperGas = keeperGas(_pool, _gasPrice, _gasSpent); // tip percent in wad units bytes16 _tipPercent = ABDKMathQuad.fromUInt(keeperTip(_savedPreviousUpdatedTimestamp, _poolInterval)); // amount of settlement tokens to give to the keeper _tipPercent = ABDKMathQuad.div(_tipPercent, ABDKMathQuad.fromUInt(100)); int256 wadRewardValue = ABDKMathQuad.toInt( ABDKMathQuad.add( ABDKMathQuad.fromUInt(_keeperGas), ABDKMathQuad.div((ABDKMathQuad.mul(ABDKMathQuad.fromUInt(_keeperGas), _tipPercent)), fixedPoint) ) ); uint256 decimals = IERC20DecimalsWrapper(ILeveragedPool(_pool).quoteToken()).decimals(); uint256 deWadifiedReward = PoolSwapLibrary.fromWad(uint256(wadRewardValue), decimals); // _keeperGas + _keeperGas * percentTip return deWadifiedReward; } /** * @notice Compensation a keeper will receive for their gas expenditure * @param _pool Address of the given pool * @param _gasPrice Price of a single gas unit (in ETH) * @param _gasSpent Number of gas units spent * @return Keeper's gas compensation */ function keeperGas( address _pool, uint256 _gasPrice, uint256 _gasSpent ) public view returns (uint256) { int256 settlementTokenPrice = IOracleWrapper(ILeveragedPool(_pool).settlementEthOracle()).getPrice(); if (settlementTokenPrice <= 0) { return 0; } else { /* safe due to explicit bounds check above */ /* (wei * Settlement / ETH) / fixed point (10^18) = amount in settlement */ bytes16 _weiSpent = ABDKMathQuad.fromUInt(_gasPrice * _gasSpent); bytes16 _settlementTokenPrice = ABDKMathQuad.fromUInt(uint256(settlementTokenPrice)); return ABDKMathQuad.toUInt(ABDKMathQuad.div(ABDKMathQuad.mul(_weiSpent, _settlementTokenPrice), fixedPoint)); } } /** * @notice Tip a keeper will receive for successfully updating the specified pool * @param _savedPreviousUpdatedTimestamp Last timestamp when the pool's price execution happened * @param _poolInterval Pool interval of the given pool * @return Percent of the `keeperGas` cost to add to payment, as a percent */ function keeperTip(uint256 _savedPreviousUpdatedTimestamp, uint256 _poolInterval) public view returns (uint256) { /* the number of blocks that have elapsed since the given pool's updateInterval passed */ uint256 elapsedBlocksNumerator = (block.timestamp - (_savedPreviousUpdatedTimestamp + _poolInterval)); uint256 keeperTip = BASE_TIP + (TIP_DELTA_PER_BLOCK * elapsedBlocksNumerator) / BLOCK_TIME; // In case of network outages or otherwise, we want to cap the tip so that the keeper cost isn't unbounded if (keeperTip > 100) { return 100; } else { return keeperTip; } } function setFactory(address _factory) external override onlyOwner { factory = IPoolFactory(_factory); } /** * @notice Sets the gas price to be used in compensating keepers for successful upkeep * @param _price Price (in ETH) per unit gas * @dev Only owner */ function setGasPrice(uint256 _price) external onlyOwner { gasPrice = _price; } modifier onlyFactory() { require(msg.sender == address(factory), "Caller not factory"); _; } }
//SPDX-License-Identifier: CC-BY-NC-ND-4.0 pragma solidity 0.8.7; /// @title The manager contract interface for multiple markets and the pools in them interface IPoolKeeper { // #### Events /** * @notice Creates a notification when a pool is created * @param poolAddress The pool address of the newly created pool * @param firstPrice The price of the market oracle when the pool was created */ event PoolAdded(address indexed poolAddress, int256 indexed firstPrice); /** * @notice Creates a notification when a call to LeveragedPool:poolUpkeep is successful * @param pool The pool address being upkept * @param data Extra data about the price fetch. This could be roundID in the case of Chainlink Oracles * @param startPrice The previous price of the pool * @param endPrice The new price of the pool */ event UpkeepSuccessful(address indexed pool, bytes data, int256 indexed startPrice, int256 indexed endPrice); /** * @notice Creates a notification when a keeper is paid for doing upkeep for a pool * @param _pool Address of pool being upkept * @param keeper Keeper to be rewarded for upkeeping * @param reward Keeper's reward (in settlement tokens) */ event KeeperPaid(address indexed _pool, address indexed keeper, uint256 reward); /** * @notice Creates a notification when a keeper's payment for upkeeping a pool failed * @param _pool Address of pool being upkept * @param keeper Keeper to be rewarded for upkeeping * @param expectedReward Keeper's expected reward (in settlement tokens); not actually transferred */ event KeeperPaymentError(address indexed _pool, address indexed keeper, uint256 expectedReward); /** * @notice Creates a notification of a failed pool update * @param pool The pool that failed to update * @param reason The reason for the error */ event PoolUpkeepError(address indexed pool, string reason); // #### Functions function newPool(address _poolAddress) external; function setFactory(address _factory) external; function checkUpkeepSinglePool(address pool) external view returns (bool); function checkUpkeepMultiplePools(address[] calldata pools) external view returns (bool); function performUpkeepSinglePool(address pool) external; function performUpkeepMultiplePools(address[] calldata pools) external; }
//SPDX-License-Identifier: CC-BY-NC-ND-4.0 pragma solidity 0.8.7; /// @title The oracle wrapper contract interface interface IOracleWrapper { function oracle() external view returns (address); // #### Functions /** * @notice Sets the oracle for a given market * @dev Should be secured, ideally only allowing the PoolKeeper to access * @param _oracle The oracle to set for the market */ function setOracle(address _oracle) external; /** * @notice Returns the current price for the asset in question * @return The latest price */ function getPrice() external view returns (int256); /** * @return _price The latest round data price * @return _data The metadata. Implementations can choose what data to return here */ function getPriceAndMetadata() external view returns (int256 _price, bytes memory _data); /** * @notice Converts from a WAD to normal value * @return Converted non-WAD value */ function fromWad(int256 wad) external view returns (int256); }
//SPDX-License-Identifier: CC-BY-NC-ND-4.0 pragma solidity 0.8.7; /// @title The contract factory for the keeper and pool contracts. Utilizes minimal clones to keep gas costs low interface IPoolFactory { struct PoolDeployment { string poolName; // The name to identify a pool by uint32 frontRunningInterval; // The minimum number of seconds that must elapse before a commit can be executed. Must be smaller than or equal to the update interval to prevent deadlock uint32 updateInterval; // The minimum number of seconds that must elapse before a price change uint16 leverageAmount; // The amount of exposure to price movements for the pool address quoteToken; // The digital asset that the pool accepts address oracleWrapper; // The IOracleWrapper implementation for fetching price feed data address settlementEthOracle; // The oracle to fetch the price of Ether in terms of the settlement token uint128 minimumCommitSize; // The minimum amount (in settlement tokens) that a user can commit in a single commitment uint128 maximumCommitQueueLength; // The maximum number of commitments that can be made for a given updateInterval } // #### Events /** * @notice Creates a notification when a pool is deployed * @param pool Address of the new pool * @param ticker Ticker of the neew pool */ event DeployPool(address indexed pool, string ticker); // #### Getters for Globals function pools(uint256 id) external view returns (address); function numPools() external view returns (uint256); function isValidPool(address _pool) external view returns (bool); // #### Functions function deployPool(PoolDeployment calldata deploymentParameters) external returns (address); function getOwner() external returns (address); function setPoolKeeper(address _poolKeeper) external; function setMaxLeverage(uint16 newMaxLeverage) external; function setFeeReceiver(address _feeReceiver) external; function setFee(uint256 _fee) external; function setPoolCommitterDeployer(address _poolCommitterDeployer) external; }
//SPDX-License-Identifier: CC-BY-NC-ND-4.0 pragma solidity 0.8.7; /// @title The pool controller contract interface interface ILeveragedPool { // Initialisation parameters for new market struct Initialization { address _owner; // Owner of the contract address _keeper; // The address of the PoolKeeper contract address _oracleWrapper; // The oracle wrapper for the derivative price feed address _settlementEthOracle; // The oracle wrapper for the SettlementToken/ETH price feed address _longToken; // Address of the long pool token address _shortToken; // Address of the short pool token address _poolCommitter; // Address of the PoolCommitter contract string _poolName; // The pool identification name uint32 _frontRunningInterval; // The minimum number of seconds that must elapse before a commit is forced to wait until the next interval uint32 _updateInterval; // The minimum number of seconds that must elapse before a commit can be executed uint256 _fee; // The fund movement fee. This amount is extracted from the deposited asset with every update and sent to the fee address uint16 _leverageAmount; // The amount of exposure to price movements for the pool address _feeAddress; // The address that the fund movement fee is sent to address _quoteToken; // The digital asset that the pool accepts. Must have a decimals() function } // #### Events /** * @notice Creates a notification when the pool is setup and ready for use * @param longToken The address of the LONG pair token * @param shortToken The address of the SHORT pair token * @param quoteToken The address of the digital asset that the pool accepts * @param poolName The pool code for the pool */ event PoolInitialized(address indexed longToken, address indexed shortToken, address quoteToken, string poolName); /** * @notice Creates a notification when the pool is rebalanced * @param shortBalanceChange The change of funds in the short side * @param longBalanceChange The change of funds in the long side */ event PoolRebalance(int256 shortBalanceChange, int256 longBalanceChange); /** * @notice Creates a notification when the pool's price execution fails * @param startPrice Price prior to price change execution * @param endPrice Price during price change execution */ event PriceChangeError(int256 indexed startPrice, int256 indexed endPrice); /** * @notice Represents change in fee receiver's address * @param oldAddress Previous address * @param newAddress Address after change */ event FeeAddressUpdated(address indexed oldAddress, address indexed newAddress); /** * @notice Represents change in keeper's address * @param oldAddress Previous address * @param newAddress Address after change */ event KeeperAddressChanged(address indexed oldAddress, address indexed newAddress); /** * @notice Represents proposed change in governance address * @param newAddress Proposed address */ event ProvisionalGovernanceChanged(address indexed newAddress); /** * @notice Represents change in governance address * @param oldAddress Previous address * @param newAddress Address after change */ event GovernanceAddressChanged(address indexed oldAddress, address indexed newAddress); function leverageAmount() external view returns (bytes16); function poolCommitter() external view returns (address); function quoteToken() external view returns (address); function oracleWrapper() external view returns (address); function lastPriceTimestamp() external view returns (uint256); function poolName() external view returns (string calldata); function updateInterval() external view returns (uint32); function shortBalance() external view returns (uint256); function longBalance() external view returns (uint256); function frontRunningInterval() external view returns (uint32); function poolTokens() external view returns (address[2] memory); function settlementEthOracle() external view returns (address); // #### Functions /** * @notice Configures the pool on deployment. The pools are EIP 1167 clones. * @dev This should only be able to be run once to prevent abuse of the pool. Use of Openzeppelin Initializable or similar is recommended * @param initialization The struct Initialization containing initialization data */ function initialize(Initialization calldata initialization) external; function poolUpkeep(int256 _oldPrice, int256 _newPrice) external; function quoteTokenTransferFrom( address from, address to, uint256 amount ) external; function payKeeperFromBalances(address to, uint256 amount) external returns (bool); function quoteTokenTransfer(address to, uint256 amount) external; function setNewPoolBalances(uint256 _longBalance, uint256 _shortBalance) external; /** * @return _latestPrice The oracle price * @return _data The oracleWrapper's metadata. Implementations can choose what data to return here * @return _lastPriceTimestamp The timestamp of the last upkeep * @return _updateInterval The update frequency for this pool * @dev To save gas so PoolKeeper does not have to make three external calls */ function getUpkeepInformation() external view returns ( int256 _latestPrice, bytes memory _data, uint256 _lastPriceTimestamp, uint256 _updateInterval ); function getOraclePrice() external view returns (int256); function intervalPassed() external view returns (bool); function balances() external view returns (uint256 _shortBalance, uint256 _longBalance); function setKeeper(address _keeper) external; function transferGovernance(address _governance) external; function claimGovernance() external; function updateFeeAddress(address account) external; function mintTokens( uint256 token, uint256 amount, address burner ) external; function burnTokens( uint256 token, uint256 amount, address burner ) external; }
//SPDX-License-Identifier: CC-BY-NC-ND-4.0 pragma solidity 0.8.7; /// @title The decimals interface for extending the ERC20 interface interface IERC20DecimalsWrapper { function decimals() external view returns (uint8); }
//SPDX-License-Identifier: CC-BY-NC-ND-4.0 pragma solidity 0.8.7; import "abdk-libraries-solidity/ABDKMathQuad.sol"; /// @title Library for various useful (mostly) mathematical functions library PoolSwapLibrary { bytes16 public constant one = 0x3fff0000000000000000000000000000; bytes16 public constant zero = 0x00000000000000000000000000000000; /* ABDKMathQuad defines this but it's private */ bytes16 private constant NEGATIVE_ZERO = 0x80000000000000000000000000000000; uint256 public constant MAX_DECIMALS = 18; uint256 public constant WAD_PRECISION = 10**18; struct PriceChangeData { int256 oldPrice; int256 newPrice; uint256 longBalance; uint256 shortBalance; bytes16 leverageAmount; bytes16 fee; } /** * @notice Calculates the ratio between two numbers * @dev Rounds any overflow towards 0. If either parameter is zero, the ratio is 0 * @param _numerator The "parts per" side of the equation. If this is zero, the ratio is zero * @param _denominator The "per part" side of the equation. If this is zero, the ratio is zero * @return the ratio, as an ABDKMathQuad number (IEEE 754 quadruple precision floating point) */ function getRatio(uint256 _numerator, uint256 _denominator) public pure returns (bytes16) { // Catch the divide by zero error. if (_denominator == 0) { return 0; } return ABDKMathQuad.div(ABDKMathQuad.fromUInt(_numerator), ABDKMathQuad.fromUInt(_denominator)); } /** * @notice Gets the short and long balances after the keeper rewards have been paid out * Keeper rewards are paid proportionally to the short and long pool * @dev Assumes shortBalance + longBalance >= reward * @param reward Amount of keeper reward * @param shortBalance Short balance of the pool * @param longBalance Long balance of the pool * @return shortBalanceAfterFees Short balance of the pool after the keeper reward has been paid * @return longBalanceAfterFees Long balance of the pool after the keeper reward has been paid */ function getBalancesAfterFees( uint256 reward, uint256 shortBalance, uint256 longBalance ) external pure returns (uint256, uint256) { bytes16 ratioShort = getRatio(shortBalance, shortBalance + longBalance); uint256 shortFees = convertDecimalToUInt(multiplyDecimalByUInt(ratioShort, reward)); uint256 shortBalanceAfterFees = shortBalance - shortFees; uint256 longBalanceAfterFees = longBalance - (reward - shortFees); // Return shortBalance and longBalance after rewards are paid out return (shortBalanceAfterFees, longBalanceAfterFees); } /** * @notice Compares two decimal numbers * @param x The first number to compare * @param y The second number to compare * @return -1 if x < y, 0 if x = y, or 1 if x > y */ function compareDecimals(bytes16 x, bytes16 y) public pure returns (int8) { return ABDKMathQuad.cmp(x, y); } /** * @notice Converts an integer value to a compatible decimal value * @param amount The amount to convert * @return The amount as a IEEE754 quadruple precision number */ function convertUIntToDecimal(uint256 amount) external pure returns (bytes16) { return ABDKMathQuad.fromUInt(amount); } /** * @notice Converts a raw decimal value to a more readable uint256 value * @param ratio The value to convert * @return The converted value */ function convertDecimalToUInt(bytes16 ratio) public pure returns (uint256) { return ABDKMathQuad.toUInt(ratio); } /** * @notice Multiplies a decimal and an unsigned integer * @param a The first term * @param b The second term * @return The product of a*b as a decimal */ function multiplyDecimalByUInt(bytes16 a, uint256 b) public pure returns (bytes16) { return ABDKMathQuad.mul(a, ABDKMathQuad.fromUInt(b)); } /** * @notice Divides two integers * @param a The dividend * @param b The divisor * @return The quotient */ function divInt(int256 a, int256 b) public pure returns (bytes16) { return ABDKMathQuad.div(ABDKMathQuad.fromInt(a), ABDKMathQuad.fromInt(b)); } /** * @notice Calculates the loss multiplier to apply to the losing pool. Includes the power leverage * @param ratio The ratio of new price to old price * @param direction The direction of the change. -1 if it's decreased, 0 if it hasn't changed, and 1 if it's increased * @param leverage The amount of leverage to apply * @return The multiplier */ function getLossMultiplier( bytes16 ratio, int8 direction, bytes16 leverage ) public pure returns (bytes16) { // If decreased: 2 ^ (leverage * log2[(1 * new/old) + [(0 * 1) / new/old]]) // = 2 ^ (leverage * log2[(new/old)]) // If increased: 2 ^ (leverage * log2[(0 * new/old) + [(1 * 1) / new/old]]) // = 2 ^ (leverage * log2([1 / new/old])) // = 2 ^ (leverage * log2([old/new])) return ABDKMathQuad.pow_2( ABDKMathQuad.mul(leverage, ABDKMathQuad.log_2(direction < 0 ? ratio : ABDKMathQuad.div(one, ratio))) ); } /** * @notice Calculates the amount to take from the losing pool * @param lossMultiplier The multiplier to use * @param balance The balance of the losing pool */ function getLossAmount(bytes16 lossMultiplier, uint256 balance) public pure returns (uint256) { return ABDKMathQuad.toUInt( ABDKMathQuad.mul(ABDKMathQuad.sub(one, lossMultiplier), ABDKMathQuad.fromUInt(balance)) ); } /** * @notice Calculates the effect of a price change. This involves calculating how many funds to transfer from the losing pool to the other. * @dev This function should be called by the LeveragedPool. * @param priceChange The struct containing necessary data to calculate price change */ function calculatePriceChange(PriceChangeData memory priceChange) external pure returns ( uint256, uint256, uint256 ) { uint256 shortBalance = priceChange.shortBalance; uint256 longBalance = priceChange.longBalance; bytes16 leverageAmount = priceChange.leverageAmount; int256 oldPrice = priceChange.oldPrice; int256 newPrice = priceChange.newPrice; bytes16 fee = priceChange.fee; // Calculate fees from long and short sides uint256 longFeeAmount = convertDecimalToUInt(multiplyDecimalByUInt(fee, longBalance)) / PoolSwapLibrary.WAD_PRECISION; uint256 shortFeeAmount = convertDecimalToUInt(multiplyDecimalByUInt(fee, shortBalance)) / PoolSwapLibrary.WAD_PRECISION; shortBalance = shortBalance - shortFeeAmount; longBalance = longBalance - longFeeAmount; uint256 totalFeeAmount = shortFeeAmount + longFeeAmount; // Use the ratio to determine if the price increased or decreased and therefore which direction // the funds should be transferred towards. bytes16 ratio = divInt(newPrice, oldPrice); int8 direction = compareDecimals(ratio, PoolSwapLibrary.one); // Take into account the leverage bytes16 lossMultiplier = getLossMultiplier(ratio, direction, leverageAmount); if (direction >= 0 && shortBalance > 0) { // Move funds from short to long pair uint256 lossAmount = getLossAmount(lossMultiplier, shortBalance); shortBalance = shortBalance - lossAmount; longBalance = longBalance + lossAmount; } else if (direction < 0 && longBalance > 0) { // Move funds from long to short pair uint256 lossAmount = getLossAmount(lossMultiplier, longBalance); shortBalance = shortBalance + lossAmount; longBalance = longBalance - lossAmount; } return (longBalance, shortBalance, totalFeeAmount); } /** * @notice Returns true if the given timestamp is BEFORE the frontRunningInterval starts, * which is allowed for uncommitment. * @dev If you try to uncommit AFTER the frontRunningInterval, it should revert. * @param subjectTime The timestamp for which you want to calculate if it was beforeFrontRunningInterval * @param lastPriceTimestamp The timestamp of the last price update * @param updateInterval The interval between price updates * @param frontRunningInterval The window of time before a price udpate users can not uncommit or have their commit executed from */ function isBeforeFrontRunningInterval( uint256 subjectTime, uint256 lastPriceTimestamp, uint256 updateInterval, uint256 frontRunningInterval ) external pure returns (bool) { return lastPriceTimestamp + updateInterval - frontRunningInterval > subjectTime; } /** * @notice Gets the number of settlement tokens to be withdrawn based on a pool token burn amount * @dev Calculates as `balance * amountIn / (tokenSupply + shadowBalance) * @param tokenSupply Total supply of pool tokens * @param amountIn Commitment amount of collateral tokens going into the pool * @param balance Balance of the pool (no. of underlying collateral tokens in pool) * @param shadowBalance Balance the shadow pool at time of mint * @return Number of settlement tokens to be withdrawn on a burn */ function getWithdrawAmountOnBurn( uint256 tokenSupply, uint256 amountIn, uint256 balance, uint256 shadowBalance ) external pure returns (uint256) { require(amountIn > 0, "Invalid amount"); // Catch the divide by zero error. if (balance == 0 || tokenSupply + shadowBalance == 0) { return amountIn; } bytes16 numerator = ABDKMathQuad.mul(ABDKMathQuad.fromUInt(balance), ABDKMathQuad.fromUInt(amountIn)); return ABDKMathQuad.toUInt(ABDKMathQuad.div(numerator, ABDKMathQuad.fromUInt(tokenSupply + shadowBalance))); } /** * @notice Gets the number of pool tokens to be minted based on existing tokens * @dev Calculated as (tokenSupply + shadowBalance) * amountIn / balance * @param tokenSupply Total supply of pool tokens * @param amountIn Commitment amount of collateral tokens going into the pool * @param balance Balance of the pool (no. of underlying collateral tokens in pool) * @param shadowBalance Balance the shadow pool at time of mint * @return Number of pool tokens to be minted */ function getMintAmount( uint256 tokenSupply, uint256 amountIn, uint256 balance, uint256 shadowBalance ) external pure returns (uint256) { require(amountIn > 0, "Invalid amount"); // Catch the divide by zero error. if (balance == 0 || tokenSupply + shadowBalance == 0) { return amountIn; } bytes16 numerator = ABDKMathQuad.mul( ABDKMathQuad.fromUInt(tokenSupply + shadowBalance), ABDKMathQuad.fromUInt(amountIn) ); return ABDKMathQuad.toUInt(ABDKMathQuad.div(numerator, ABDKMathQuad.fromUInt(balance))); } /** * @notice Converts from a WAD to normal value * @return Converted non-WAD value */ function fromWad(uint256 _wadValue, uint256 _decimals) external pure returns (uint256) { uint256 scaler = 10**(MAX_DECIMALS - _decimals); return _wadValue / scaler; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _setOwner(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for * deploying minimal proxy contracts, also known as "clones". * * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies * > a minimal bytecode implementation that delegates all calls to a known, fixed address. * * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the * deterministic method. * * _Available since v3.4._ */ library Clones { /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create opcode, which should never revert. */ function clone(address implementation) internal returns (address instance) { assembly { let ptr := mload(0x40) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) mstore(add(ptr, 0x14), shl(0x60, implementation)) mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) instance := create(0, ptr, 0x37) } require(instance != address(0), "ERC1167: create failed"); } /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create2 opcode and a `salt` to deterministically deploy * the clone. Using the same `implementation` and `salt` multiple time will revert, since * the clones cannot be deployed twice at the same address. */ function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) { assembly { let ptr := mload(0x40) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) mstore(add(ptr, 0x14), shl(0x60, implementation)) mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) instance := create2(0, ptr, 0x37, salt) } require(instance != address(0), "ERC1167: create2 failed"); } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt, address deployer ) internal pure returns (address predicted) { assembly { let ptr := mload(0x40) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) mstore(add(ptr, 0x14), shl(0x60, implementation)) mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000) mstore(add(ptr, 0x38), shl(0x60, deployer)) mstore(add(ptr, 0x4c), salt) mstore(add(ptr, 0x6c), keccak256(ptr, 0x37)) predicted := keccak256(add(ptr, 0x37), 0x55) } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress(address implementation, bytes32 salt) internal view returns (address predicted) { return predictDeterministicAddress(implementation, salt, address(this)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: BSD-4-Clause /* * ABDK Math Quad Smart Contract Library. Copyright © 2019 by ABDK Consulting. * Author: Mikhail Vladimirov <[email protected]> */ pragma solidity ^0.8.0; /** * Smart contract library of mathematical functions operating with IEEE 754 * quadruple-precision binary floating-point numbers (quadruple precision * numbers). As long as quadruple precision numbers are 16-bytes long, they are * represented by bytes16 type. */ library ABDKMathQuad { /* * 0. */ bytes16 private constant POSITIVE_ZERO = 0x00000000000000000000000000000000; /* * -0. */ bytes16 private constant NEGATIVE_ZERO = 0x80000000000000000000000000000000; /* * +Infinity. */ bytes16 private constant POSITIVE_INFINITY = 0x7FFF0000000000000000000000000000; /* * -Infinity. */ bytes16 private constant NEGATIVE_INFINITY = 0xFFFF0000000000000000000000000000; /* * Canonical NaN value. */ bytes16 private constant NaN = 0x7FFF8000000000000000000000000000; /** * Convert signed 256-bit integer number into quadruple precision number. * * @param x signed 256-bit integer number * @return quadruple precision number */ function fromInt (int256 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16 (0); else { // We rely on overflow behavior here uint256 result = uint256 (x > 0 ? x : -x); uint256 msb = mostSignificantBit (result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16383 + msb << 112; if (x < 0) result |= 0x80000000000000000000000000000000; return bytes16 (uint128 (result)); } } } /** * Convert quadruple precision number into signed 256-bit integer number * rounding towards zero. Revert on overflow. * * @param x quadruple precision number * @return signed 256-bit integer number */ function toInt (bytes16 x) internal pure returns (int256) { unchecked { uint256 exponent = uint128 (x) >> 112 & 0x7FFF; require (exponent <= 16638); // Overflow if (exponent < 16383) return 0; // Underflow uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 0x10000000000000000000000000000; if (exponent < 16495) result >>= 16495 - exponent; else if (exponent > 16495) result <<= exponent - 16495; if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative require (result <= 0x8000000000000000000000000000000000000000000000000000000000000000); return -int256 (result); // We rely on overflow behavior here } else { require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int256 (result); } } } /** * Convert unsigned 256-bit integer number into quadruple precision number. * * @param x unsigned 256-bit integer number * @return quadruple precision number */ function fromUInt (uint256 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16 (0); else { uint256 result = x; uint256 msb = mostSignificantBit (result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16383 + msb << 112; return bytes16 (uint128 (result)); } } } /** * Convert quadruple precision number into unsigned 256-bit integer number * rounding towards zero. Revert on underflow. Note, that negative floating * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer * without error, because they are rounded to zero. * * @param x quadruple precision number * @return unsigned 256-bit integer number */ function toUInt (bytes16 x) internal pure returns (uint256) { unchecked { uint256 exponent = uint128 (x) >> 112 & 0x7FFF; if (exponent < 16383) return 0; // Underflow require (uint128 (x) < 0x80000000000000000000000000000000); // Negative require (exponent <= 16638); // Overflow uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 0x10000000000000000000000000000; if (exponent < 16495) result >>= 16495 - exponent; else if (exponent > 16495) result <<= exponent - 16495; return result; } } /** * Convert signed 128.128 bit fixed point number into quadruple precision * number. * * @param x signed 128.128 bit fixed point number * @return quadruple precision number */ function from128x128 (int256 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16 (0); else { // We rely on overflow behavior here uint256 result = uint256 (x > 0 ? x : -x); uint256 msb = mostSignificantBit (result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16255 + msb << 112; if (x < 0) result |= 0x80000000000000000000000000000000; return bytes16 (uint128 (result)); } } } /** * Convert quadruple precision number into signed 128.128 bit fixed point * number. Revert on overflow. * * @param x quadruple precision number * @return signed 128.128 bit fixed point number */ function to128x128 (bytes16 x) internal pure returns (int256) { unchecked { uint256 exponent = uint128 (x) >> 112 & 0x7FFF; require (exponent <= 16510); // Overflow if (exponent < 16255) return 0; // Underflow uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 0x10000000000000000000000000000; if (exponent < 16367) result >>= 16367 - exponent; else if (exponent > 16367) result <<= exponent - 16367; if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative require (result <= 0x8000000000000000000000000000000000000000000000000000000000000000); return -int256 (result); // We rely on overflow behavior here } else { require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int256 (result); } } } /** * Convert signed 64.64 bit fixed point number into quadruple precision * number. * * @param x signed 64.64 bit fixed point number * @return quadruple precision number */ function from64x64 (int128 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16 (0); else { // We rely on overflow behavior here uint256 result = uint128 (x > 0 ? x : -x); uint256 msb = mostSignificantBit (result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16319 + msb << 112; if (x < 0) result |= 0x80000000000000000000000000000000; return bytes16 (uint128 (result)); } } } /** * Convert quadruple precision number into signed 64.64 bit fixed point * number. Revert on overflow. * * @param x quadruple precision number * @return signed 64.64 bit fixed point number */ function to64x64 (bytes16 x) internal pure returns (int128) { unchecked { uint256 exponent = uint128 (x) >> 112 & 0x7FFF; require (exponent <= 16446); // Overflow if (exponent < 16319) return 0; // Underflow uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 0x10000000000000000000000000000; if (exponent < 16431) result >>= 16431 - exponent; else if (exponent > 16431) result <<= exponent - 16431; if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative require (result <= 0x80000000000000000000000000000000); return -int128 (int256 (result)); // We rely on overflow behavior here } else { require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int128 (int256 (result)); } } } /** * Convert octuple precision number into quadruple precision number. * * @param x octuple precision number * @return quadruple precision number */ function fromOctuple (bytes32 x) internal pure returns (bytes16) { unchecked { bool negative = x & 0x8000000000000000000000000000000000000000000000000000000000000000 > 0; uint256 exponent = uint256 (x) >> 236 & 0x7FFFF; uint256 significand = uint256 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (exponent == 0x7FFFF) { if (significand > 0) return NaN; else return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY; } if (exponent > 278526) return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY; else if (exponent < 245649) return negative ? NEGATIVE_ZERO : POSITIVE_ZERO; else if (exponent < 245761) { significand = (significand | 0x100000000000000000000000000000000000000000000000000000000000) >> 245885 - exponent; exponent = 0; } else { significand >>= 124; exponent -= 245760; } uint128 result = uint128 (significand | exponent << 112); if (negative) result |= 0x80000000000000000000000000000000; return bytes16 (result); } } /** * Convert quadruple precision number into octuple precision number. * * @param x quadruple precision number * @return octuple precision number */ function toOctuple (bytes16 x) internal pure returns (bytes32) { unchecked { uint256 exponent = uint128 (x) >> 112 & 0x7FFF; uint256 result = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (exponent == 0x7FFF) exponent = 0x7FFFF; // Infinity or NaN else if (exponent == 0) { if (result > 0) { uint256 msb = mostSignificantBit (result); result = result << 236 - msb & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; exponent = 245649 + msb; } } else { result <<= 124; exponent += 245760; } result |= exponent << 236; if (uint128 (x) >= 0x80000000000000000000000000000000) result |= 0x8000000000000000000000000000000000000000000000000000000000000000; return bytes32 (result); } } /** * Convert double precision number into quadruple precision number. * * @param x double precision number * @return quadruple precision number */ function fromDouble (bytes8 x) internal pure returns (bytes16) { unchecked { uint256 exponent = uint64 (x) >> 52 & 0x7FF; uint256 result = uint64 (x) & 0xFFFFFFFFFFFFF; if (exponent == 0x7FF) exponent = 0x7FFF; // Infinity or NaN else if (exponent == 0) { if (result > 0) { uint256 msb = mostSignificantBit (result); result = result << 112 - msb & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; exponent = 15309 + msb; } } else { result <<= 60; exponent += 15360; } result |= exponent << 112; if (x & 0x8000000000000000 > 0) result |= 0x80000000000000000000000000000000; return bytes16 (uint128 (result)); } } /** * Convert quadruple precision number into double precision number. * * @param x quadruple precision number * @return double precision number */ function toDouble (bytes16 x) internal pure returns (bytes8) { unchecked { bool negative = uint128 (x) >= 0x80000000000000000000000000000000; uint256 exponent = uint128 (x) >> 112 & 0x7FFF; uint256 significand = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (exponent == 0x7FFF) { if (significand > 0) return 0x7FF8000000000000; // NaN else return negative ? bytes8 (0xFFF0000000000000) : // -Infinity bytes8 (0x7FF0000000000000); // Infinity } if (exponent > 17406) return negative ? bytes8 (0xFFF0000000000000) : // -Infinity bytes8 (0x7FF0000000000000); // Infinity else if (exponent < 15309) return negative ? bytes8 (0x8000000000000000) : // -0 bytes8 (0x0000000000000000); // 0 else if (exponent < 15361) { significand = (significand | 0x10000000000000000000000000000) >> 15421 - exponent; exponent = 0; } else { significand >>= 60; exponent -= 15360; } uint64 result = uint64 (significand | exponent << 52); if (negative) result |= 0x8000000000000000; return bytes8 (result); } } /** * Test whether given quadruple precision number is NaN. * * @param x quadruple precision number * @return true if x is NaN, false otherwise */ function isNaN (bytes16 x) internal pure returns (bool) { unchecked { return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF > 0x7FFF0000000000000000000000000000; } } /** * Test whether given quadruple precision number is positive or negative * infinity. * * @param x quadruple precision number * @return true if x is positive or negative infinity, false otherwise */ function isInfinity (bytes16 x) internal pure returns (bool) { unchecked { return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x7FFF0000000000000000000000000000; } } /** * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x * is positive. Note that sign (-0) is zero. Revert if x is NaN. * * @param x quadruple precision number * @return sign of x */ function sign (bytes16 x) internal pure returns (int8) { unchecked { uint128 absoluteX = uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; require (absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN if (absoluteX == 0) return 0; else if (uint128 (x) >= 0x80000000000000000000000000000000) return -1; else return 1; } } /** * Calculate sign (x - y). Revert if either argument is NaN, or both * arguments are infinities of the same sign. * * @param x quadruple precision number * @param y quadruple precision number * @return sign (x - y) */ function cmp (bytes16 x, bytes16 y) internal pure returns (int8) { unchecked { uint128 absoluteX = uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; require (absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN uint128 absoluteY = uint128 (y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; require (absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN // Not infinities of the same sign require (x != y || absoluteX < 0x7FFF0000000000000000000000000000); if (x == y) return 0; else { bool negativeX = uint128 (x) >= 0x80000000000000000000000000000000; bool negativeY = uint128 (y) >= 0x80000000000000000000000000000000; if (negativeX) { if (negativeY) return absoluteX > absoluteY ? -1 : int8 (1); else return -1; } else { if (negativeY) return 1; else return absoluteX > absoluteY ? int8 (1) : -1; } } } } /** * Test whether x equals y. NaN, infinity, and -infinity are not equal to * anything. * * @param x quadruple precision number * @param y quadruple precision number * @return true if x equals to y, false otherwise */ function eq (bytes16 x, bytes16 y) internal pure returns (bool) { unchecked { if (x == y) { return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF < 0x7FFF0000000000000000000000000000; } else return false; } } /** * Calculate x + y. Special values behave in the following way: * * NaN + x = NaN for any x. * Infinity + x = Infinity for any finite x. * -Infinity + x = -Infinity for any finite x. * Infinity + Infinity = Infinity. * -Infinity + -Infinity = -Infinity. * Infinity + -Infinity = -Infinity + Infinity = NaN. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function add (bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; uint256 yExponent = uint128 (y) >> 112 & 0x7FFF; if (xExponent == 0x7FFF) { if (yExponent == 0x7FFF) { if (x == y) return x; else return NaN; } else return x; } else if (yExponent == 0x7FFF) return y; else { bool xSign = uint128 (x) >= 0x80000000000000000000000000000000; uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; bool ySign = uint128 (y) >= 0x80000000000000000000000000000000; uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (yExponent == 0) yExponent = 1; else ySignifier |= 0x10000000000000000000000000000; if (xSignifier == 0) return y == NEGATIVE_ZERO ? POSITIVE_ZERO : y; else if (ySignifier == 0) return x == NEGATIVE_ZERO ? POSITIVE_ZERO : x; else { int256 delta = int256 (xExponent) - int256 (yExponent); if (xSign == ySign) { if (delta > 112) return x; else if (delta > 0) ySignifier >>= uint256 (delta); else if (delta < -112) return y; else if (delta < 0) { xSignifier >>= uint256 (-delta); xExponent = yExponent; } xSignifier += ySignifier; if (xSignifier >= 0x20000000000000000000000000000) { xSignifier >>= 1; xExponent += 1; } if (xExponent == 0x7FFF) return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY; else { if (xSignifier < 0x10000000000000000000000000000) xExponent = 0; else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; return bytes16 (uint128 ( (xSign ? 0x80000000000000000000000000000000 : 0) | (xExponent << 112) | xSignifier)); } } else { if (delta > 0) { xSignifier <<= 1; xExponent -= 1; } else if (delta < 0) { ySignifier <<= 1; xExponent = yExponent - 1; } if (delta > 112) ySignifier = 1; else if (delta > 1) ySignifier = (ySignifier - 1 >> uint256 (delta - 1)) + 1; else if (delta < -112) xSignifier = 1; else if (delta < -1) xSignifier = (xSignifier - 1 >> uint256 (-delta - 1)) + 1; if (xSignifier >= ySignifier) xSignifier -= ySignifier; else { xSignifier = ySignifier - xSignifier; xSign = ySign; } if (xSignifier == 0) return POSITIVE_ZERO; uint256 msb = mostSignificantBit (xSignifier); if (msb == 113) { xSignifier = xSignifier >> 1 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent += 1; } else if (msb < 112) { uint256 shift = 112 - msb; if (xExponent > shift) { xSignifier = xSignifier << shift & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent -= shift; } else { xSignifier <<= xExponent - 1; xExponent = 0; } } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0x7FFF) return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY; else return bytes16 (uint128 ( (xSign ? 0x80000000000000000000000000000000 : 0) | (xExponent << 112) | xSignifier)); } } } } } /** * Calculate x - y. Special values behave in the following way: * * NaN - x = NaN for any x. * Infinity - x = Infinity for any finite x. * -Infinity - x = -Infinity for any finite x. * Infinity - -Infinity = Infinity. * -Infinity - Infinity = -Infinity. * Infinity - Infinity = -Infinity - -Infinity = NaN. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function sub (bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { return add (x, y ^ 0x80000000000000000000000000000000); } } /** * Calculate x * y. Special values behave in the following way: * * NaN * x = NaN for any x. * Infinity * x = Infinity for any finite positive x. * Infinity * x = -Infinity for any finite negative x. * -Infinity * x = -Infinity for any finite positive x. * -Infinity * x = Infinity for any finite negative x. * Infinity * 0 = NaN. * -Infinity * 0 = NaN. * Infinity * Infinity = Infinity. * Infinity * -Infinity = -Infinity. * -Infinity * Infinity = -Infinity. * -Infinity * -Infinity = Infinity. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function mul (bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; uint256 yExponent = uint128 (y) >> 112 & 0x7FFF; if (xExponent == 0x7FFF) { if (yExponent == 0x7FFF) { if (x == y) return x ^ y & 0x80000000000000000000000000000000; else if (x ^ y == 0x80000000000000000000000000000000) return x | y; else return NaN; } else { if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; else return x ^ y & 0x80000000000000000000000000000000; } } else if (yExponent == 0x7FFF) { if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; else return y ^ x & 0x80000000000000000000000000000000; } else { uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (yExponent == 0) yExponent = 1; else ySignifier |= 0x10000000000000000000000000000; xSignifier *= ySignifier; if (xSignifier == 0) return (x ^ y) & 0x80000000000000000000000000000000 > 0 ? NEGATIVE_ZERO : POSITIVE_ZERO; xExponent += yExponent; uint256 msb = xSignifier >= 0x200000000000000000000000000000000000000000000000000000000 ? 225 : xSignifier >= 0x100000000000000000000000000000000000000000000000000000000 ? 224 : mostSignificantBit (xSignifier); if (xExponent + msb < 16496) { // Underflow xExponent = 0; xSignifier = 0; } else if (xExponent + msb < 16608) { // Subnormal if (xExponent < 16496) xSignifier >>= 16496 - xExponent; else if (xExponent > 16496) xSignifier <<= xExponent - 16496; xExponent = 0; } else if (xExponent + msb > 49373) { xExponent = 0x7FFF; xSignifier = 0; } else { if (msb > 112) xSignifier >>= msb - 112; else if (msb < 112) xSignifier <<= 112 - msb; xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent = xExponent + msb - 16607; } return bytes16 (uint128 (uint128 ((x ^ y) & 0x80000000000000000000000000000000) | xExponent << 112 | xSignifier)); } } } /** * Calculate x / y. Special values behave in the following way: * * NaN / x = NaN for any x. * x / NaN = NaN for any x. * Infinity / x = Infinity for any finite non-negative x. * Infinity / x = -Infinity for any finite negative x including -0. * -Infinity / x = -Infinity for any finite non-negative x. * -Infinity / x = Infinity for any finite negative x including -0. * x / Infinity = 0 for any finite non-negative x. * x / -Infinity = -0 for any finite non-negative x. * x / Infinity = -0 for any finite non-negative x including -0. * x / -Infinity = 0 for any finite non-negative x including -0. * * Infinity / Infinity = NaN. * Infinity / -Infinity = -NaN. * -Infinity / Infinity = -NaN. * -Infinity / -Infinity = NaN. * * Division by zero behaves in the following way: * * x / 0 = Infinity for any finite positive x. * x / -0 = -Infinity for any finite positive x. * x / 0 = -Infinity for any finite negative x. * x / -0 = Infinity for any finite negative x. * 0 / 0 = NaN. * 0 / -0 = NaN. * -0 / 0 = NaN. * -0 / -0 = NaN. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function div (bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; uint256 yExponent = uint128 (y) >> 112 & 0x7FFF; if (xExponent == 0x7FFF) { if (yExponent == 0x7FFF) return NaN; else return x ^ y & 0x80000000000000000000000000000000; } else if (yExponent == 0x7FFF) { if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN; else return POSITIVE_ZERO | (x ^ y) & 0x80000000000000000000000000000000; } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) { if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; else return POSITIVE_INFINITY | (x ^ y) & 0x80000000000000000000000000000000; } else { uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (yExponent == 0) yExponent = 1; else ySignifier |= 0x10000000000000000000000000000; uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) { if (xSignifier != 0) { uint shift = 226 - mostSignificantBit (xSignifier); xSignifier <<= shift; xExponent = 1; yExponent += shift - 114; } } else { xSignifier = (xSignifier | 0x10000000000000000000000000000) << 114; } xSignifier = xSignifier / ySignifier; if (xSignifier == 0) return (x ^ y) & 0x80000000000000000000000000000000 > 0 ? NEGATIVE_ZERO : POSITIVE_ZERO; assert (xSignifier >= 0x1000000000000000000000000000); uint256 msb = xSignifier >= 0x80000000000000000000000000000 ? mostSignificantBit (xSignifier) : xSignifier >= 0x40000000000000000000000000000 ? 114 : xSignifier >= 0x20000000000000000000000000000 ? 113 : 112; if (xExponent + msb > yExponent + 16497) { // Overflow xExponent = 0x7FFF; xSignifier = 0; } else if (xExponent + msb + 16380 < yExponent) { // Underflow xExponent = 0; xSignifier = 0; } else if (xExponent + msb + 16268 < yExponent) { // Subnormal if (xExponent + 16380 > yExponent) xSignifier <<= xExponent + 16380 - yExponent; else if (xExponent + 16380 < yExponent) xSignifier >>= yExponent - xExponent - 16380; xExponent = 0; } else { // Normal if (msb > 112) xSignifier >>= msb - 112; xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent = xExponent + msb + 16269 - yExponent; } return bytes16 (uint128 (uint128 ((x ^ y) & 0x80000000000000000000000000000000) | xExponent << 112 | xSignifier)); } } } /** * Calculate -x. * * @param x quadruple precision number * @return quadruple precision number */ function neg (bytes16 x) internal pure returns (bytes16) { unchecked { return x ^ 0x80000000000000000000000000000000; } } /** * Calculate |x|. * * @param x quadruple precision number * @return quadruple precision number */ function abs (bytes16 x) internal pure returns (bytes16) { unchecked { return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; } } /** * Calculate square root of x. Return NaN on negative x excluding -0. * * @param x quadruple precision number * @return quadruple precision number */ function sqrt (bytes16 x) internal pure returns (bytes16) { unchecked { if (uint128 (x) > 0x80000000000000000000000000000000) return NaN; else { uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; if (xExponent == 0x7FFF) return x; else { uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; if (xSignifier == 0) return POSITIVE_ZERO; bool oddExponent = xExponent & 0x1 == 0; xExponent = xExponent + 16383 >> 1; if (oddExponent) { if (xSignifier >= 0x10000000000000000000000000000) xSignifier <<= 113; else { uint256 msb = mostSignificantBit (xSignifier); uint256 shift = (226 - msb) & 0xFE; xSignifier <<= shift; xExponent -= shift - 112 >> 1; } } else { if (xSignifier >= 0x10000000000000000000000000000) xSignifier <<= 112; else { uint256 msb = mostSignificantBit (xSignifier); uint256 shift = (225 - msb) & 0xFE; xSignifier <<= shift; xExponent -= shift - 112 >> 1; } } uint256 r = 0x10000000000000000000000000000; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; // Seven iterations should be enough uint256 r1 = xSignifier / r; if (r1 < r) r = r1; return bytes16 (uint128 (xExponent << 112 | r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)); } } } } /** * Calculate binary logarithm of x. Return NaN on negative x excluding -0. * * @param x quadruple precision number * @return quadruple precision number */ function log_2 (bytes16 x) internal pure returns (bytes16) { unchecked { if (uint128 (x) > 0x80000000000000000000000000000000) return NaN; else if (x == 0x3FFF0000000000000000000000000000) return POSITIVE_ZERO; else { uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; if (xExponent == 0x7FFF) return x; else { uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; if (xSignifier == 0) return NEGATIVE_INFINITY; bool resultNegative; uint256 resultExponent = 16495; uint256 resultSignifier; if (xExponent >= 0x3FFF) { resultNegative = false; resultSignifier = xExponent - 0x3FFF; xSignifier <<= 15; } else { resultNegative = true; if (xSignifier >= 0x10000000000000000000000000000) { resultSignifier = 0x3FFE - xExponent; xSignifier <<= 15; } else { uint256 msb = mostSignificantBit (xSignifier); resultSignifier = 16493 - msb; xSignifier <<= 127 - msb; } } if (xSignifier == 0x80000000000000000000000000000000) { if (resultNegative) resultSignifier += 1; uint256 shift = 112 - mostSignificantBit (resultSignifier); resultSignifier <<= shift; resultExponent -= shift; } else { uint256 bb = resultNegative ? 1 : 0; while (resultSignifier < 0x10000000000000000000000000000) { resultSignifier <<= 1; resultExponent -= 1; xSignifier *= xSignifier; uint256 b = xSignifier >> 255; resultSignifier += b ^ bb; xSignifier >>= 127 + b; } } return bytes16 (uint128 ((resultNegative ? 0x80000000000000000000000000000000 : 0) | resultExponent << 112 | resultSignifier & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)); } } } } /** * Calculate natural logarithm of x. Return NaN on negative x excluding -0. * * @param x quadruple precision number * @return quadruple precision number */ function ln (bytes16 x) internal pure returns (bytes16) { unchecked { return mul (log_2 (x), 0x3FFE62E42FEFA39EF35793C7673007E5); } } /** * Calculate 2^x. * * @param x quadruple precision number * @return quadruple precision number */ function pow_2 (bytes16 x) internal pure returns (bytes16) { unchecked { bool xNegative = uint128 (x) > 0x80000000000000000000000000000000; uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0x7FFF && xSignifier != 0) return NaN; else if (xExponent > 16397) return xNegative ? POSITIVE_ZERO : POSITIVE_INFINITY; else if (xExponent < 16255) return 0x3FFF0000000000000000000000000000; else { if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; if (xExponent > 16367) xSignifier <<= xExponent - 16367; else if (xExponent < 16367) xSignifier >>= 16367 - xExponent; if (xNegative && xSignifier > 0x406E00000000000000000000000000000000) return POSITIVE_ZERO; if (!xNegative && xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) return POSITIVE_INFINITY; uint256 resultExponent = xSignifier >> 128; xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xNegative && xSignifier != 0) { xSignifier = ~xSignifier; resultExponent += 1; } uint256 resultSignifier = 0x80000000000000000000000000000000; if (xSignifier & 0x80000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128; if (xSignifier & 0x40000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128; if (xSignifier & 0x20000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128; if (xSignifier & 0x10000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10B5586CF9890F6298B92B71842A98363 >> 128; if (xSignifier & 0x8000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1059B0D31585743AE7C548EB68CA417FD >> 128; if (xSignifier & 0x4000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128; if (xSignifier & 0x2000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128; if (xSignifier & 0x1000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128; if (xSignifier & 0x800000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128; if (xSignifier & 0x400000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128; if (xSignifier & 0x200000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100162F3904051FA128BCA9C55C31E5DF >> 128; if (xSignifier & 0x100000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000B175EFFDC76BA38E31671CA939725 >> 128; if (xSignifier & 0x80000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128; if (xSignifier & 0x40000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128; if (xSignifier & 0x20000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000162E525EE054754457D5995292026 >> 128; if (xSignifier & 0x10000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000B17255775C040618BF4A4ADE83FC >> 128; if (xSignifier & 0x8000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128; if (xSignifier & 0x4000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128; if (xSignifier & 0x2000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000162E43F4F831060E02D839A9D16D >> 128; if (xSignifier & 0x1000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000B1721BCFC99D9F890EA06911763 >> 128; if (xSignifier & 0x800000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128; if (xSignifier & 0x400000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128; if (xSignifier & 0x200000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000162E430E5A18F6119E3C02282A5 >> 128; if (xSignifier & 0x100000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000B1721835514B86E6D96EFD1BFE >> 128; if (xSignifier & 0x80000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128; if (xSignifier & 0x40000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000002C5C8601CC6B9E94213C72737A >> 128; if (xSignifier & 0x20000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000162E42FFF037DF38AA2B219F06 >> 128; if (xSignifier & 0x10000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000B17217FBA9C739AA5819F44F9 >> 128; if (xSignifier & 0x8000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128; if (xSignifier & 0x4000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128; if (xSignifier & 0x2000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000162E42FF0999CE3541B9FFFCF >> 128; if (xSignifier & 0x1000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000B17217F80F4EF5AADDA45554 >> 128; if (xSignifier & 0x800000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000058B90BFBF8479BD5A81B51AD >> 128; if (xSignifier & 0x400000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128; if (xSignifier & 0x200000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000162E42FEFB2FED257559BDAA >> 128; if (xSignifier & 0x100000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128; if (xSignifier & 0x80000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128; if (xSignifier & 0x40000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128; if (xSignifier & 0x20000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000162E42FEFA494F1478FDE05 >> 128; if (xSignifier & 0x10000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000B17217F7D20CF927C8E94C >> 128; if (xSignifier & 0x8000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128; if (xSignifier & 0x4000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000002C5C85FDF477B662B26945 >> 128; if (xSignifier & 0x2000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000162E42FEFA3AE53369388C >> 128; if (xSignifier & 0x1000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000B17217F7D1D351A389D40 >> 128; if (xSignifier & 0x800000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128; if (xSignifier & 0x400000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000002C5C85FDF4741BEA6E77E >> 128; if (xSignifier & 0x200000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000162E42FEFA39FE95583C2 >> 128; if (xSignifier & 0x100000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000B17217F7D1CFB72B45E1 >> 128; if (xSignifier & 0x80000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128; if (xSignifier & 0x40000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000002C5C85FDF473E242EA38 >> 128; if (xSignifier & 0x20000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000162E42FEFA39F02B772C >> 128; if (xSignifier & 0x10000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000B17217F7D1CF7D83C1A >> 128; if (xSignifier & 0x8000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128; if (xSignifier & 0x4000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000002C5C85FDF473DEA871F >> 128; if (xSignifier & 0x2000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000162E42FEFA39EF44D91 >> 128; if (xSignifier & 0x1000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000B17217F7D1CF79E949 >> 128; if (xSignifier & 0x800000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000058B90BFBE8E7BCE544 >> 128; if (xSignifier & 0x400000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000002C5C85FDF473DE6ECA >> 128; if (xSignifier & 0x200000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000162E42FEFA39EF366F >> 128; if (xSignifier & 0x100000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000B17217F7D1CF79AFA >> 128; if (xSignifier & 0x80000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000058B90BFBE8E7BCD6D >> 128; if (xSignifier & 0x40000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000002C5C85FDF473DE6B2 >> 128; if (xSignifier & 0x20000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000162E42FEFA39EF358 >> 128; if (xSignifier & 0x10000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000B17217F7D1CF79AB >> 128; if (xSignifier & 0x8000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000058B90BFBE8E7BCD5 >> 128; if (xSignifier & 0x4000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000002C5C85FDF473DE6A >> 128; if (xSignifier & 0x2000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000162E42FEFA39EF34 >> 128; if (xSignifier & 0x1000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000B17217F7D1CF799 >> 128; if (xSignifier & 0x800000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000058B90BFBE8E7BCC >> 128; if (xSignifier & 0x400000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000002C5C85FDF473DE5 >> 128; if (xSignifier & 0x200000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000162E42FEFA39EF2 >> 128; if (xSignifier & 0x100000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000B17217F7D1CF78 >> 128; if (xSignifier & 0x80000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000058B90BFBE8E7BB >> 128; if (xSignifier & 0x40000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000002C5C85FDF473DD >> 128; if (xSignifier & 0x20000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000162E42FEFA39EE >> 128; if (xSignifier & 0x10000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000B17217F7D1CF6 >> 128; if (xSignifier & 0x8000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000058B90BFBE8E7A >> 128; if (xSignifier & 0x4000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000002C5C85FDF473C >> 128; if (xSignifier & 0x2000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000162E42FEFA39D >> 128; if (xSignifier & 0x1000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000B17217F7D1CE >> 128; if (xSignifier & 0x800000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000058B90BFBE8E6 >> 128; if (xSignifier & 0x400000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000002C5C85FDF472 >> 128; if (xSignifier & 0x200000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000162E42FEFA38 >> 128; if (xSignifier & 0x100000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000B17217F7D1B >> 128; if (xSignifier & 0x80000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000058B90BFBE8D >> 128; if (xSignifier & 0x40000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000002C5C85FDF46 >> 128; if (xSignifier & 0x20000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000162E42FEFA2 >> 128; if (xSignifier & 0x10000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000B17217F7D0 >> 128; if (xSignifier & 0x8000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000058B90BFBE7 >> 128; if (xSignifier & 0x4000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000002C5C85FDF3 >> 128; if (xSignifier & 0x2000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000162E42FEF9 >> 128; if (xSignifier & 0x1000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000B17217F7C >> 128; if (xSignifier & 0x800000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000058B90BFBD >> 128; if (xSignifier & 0x400000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000002C5C85FDE >> 128; if (xSignifier & 0x200000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000162E42FEE >> 128; if (xSignifier & 0x100000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000B17217F6 >> 128; if (xSignifier & 0x80000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000058B90BFA >> 128; if (xSignifier & 0x40000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000002C5C85FC >> 128; if (xSignifier & 0x20000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000162E42FD >> 128; if (xSignifier & 0x10000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000B17217E >> 128; if (xSignifier & 0x8000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000058B90BE >> 128; if (xSignifier & 0x4000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000002C5C85E >> 128; if (xSignifier & 0x2000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000162E42E >> 128; if (xSignifier & 0x1000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000B17216 >> 128; if (xSignifier & 0x800000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000058B90A >> 128; if (xSignifier & 0x400000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000002C5C84 >> 128; if (xSignifier & 0x200000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000162E41 >> 128; if (xSignifier & 0x100000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000B1720 >> 128; if (xSignifier & 0x80000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000058B8F >> 128; if (xSignifier & 0x40000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000002C5C7 >> 128; if (xSignifier & 0x20000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000162E3 >> 128; if (xSignifier & 0x10000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000B171 >> 128; if (xSignifier & 0x8000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000058B8 >> 128; if (xSignifier & 0x4000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000002C5B >> 128; if (xSignifier & 0x2000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000162D >> 128; if (xSignifier & 0x1000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000B16 >> 128; if (xSignifier & 0x800 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000058A >> 128; if (xSignifier & 0x400 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000002C4 >> 128; if (xSignifier & 0x200 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000161 >> 128; if (xSignifier & 0x100 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000000B0 >> 128; if (xSignifier & 0x80 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000057 >> 128; if (xSignifier & 0x40 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000002B >> 128; if (xSignifier & 0x20 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000015 >> 128; if (xSignifier & 0x10 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000000A >> 128; if (xSignifier & 0x8 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000004 >> 128; if (xSignifier & 0x4 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000001 >> 128; if (!xNegative) { resultSignifier = resultSignifier >> 15 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; resultExponent += 0x3FFF; } else if (resultExponent <= 0x3FFE) { resultSignifier = resultSignifier >> 15 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; resultExponent = 0x3FFF - resultExponent; } else { resultSignifier = resultSignifier >> resultExponent - 16367; resultExponent = 0; } return bytes16 (uint128 (resultExponent << 112 | resultSignifier)); } } } /** * Calculate e^x. * * @param x quadruple precision number * @return quadruple precision number */ function exp (bytes16 x) internal pure returns (bytes16) { unchecked { return pow_2 (mul (x, 0x3FFF71547652B82FE1777D0FFDA0D23A)); } } /** * Get index of the most significant non-zero bit in binary representation of * x. Reverts if x is zero. * * @return index of the most significant non-zero bit in binary representation * of x */ function mostSignificantBit (uint256 x) private pure returns (uint256) { unchecked { require (x > 0); uint256 result = 0; if (x >= 0x100000000000000000000000000000000) { x >>= 128; result += 128; } if (x >= 0x10000000000000000) { x >>= 64; result += 64; } if (x >= 0x100000000) { x >>= 32; result += 32; } if (x >= 0x10000) { x >>= 16; result += 16; } if (x >= 0x100) { x >>= 8; result += 8; } if (x >= 0x10) { x >>= 4; result += 4; } if (x >= 0x4) { x >>= 2; result += 2; } if (x >= 0x2) result += 1; // No need to shift x anymore return result; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./AggregatorInterface.sol"; import "./AggregatorV3Interface.sol"; interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface { }
// SPDX-License-Identifier: MIT 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 pragma solidity ^0.8.0; interface AggregatorInterface { 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 ); event AnswerUpdated( int256 indexed current, uint256 indexed roundId, uint256 updatedAt ); event NewRound( uint256 indexed roundId, address indexed startedBy, uint256 startedAt ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface AggregatorV3Interface { function decimals() external view returns ( uint8 ); function description() external view returns ( string memory ); function version() external view returns ( uint256 ); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. 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 ); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": { "contracts/implementation/PoolSwapLibrary.sol": { "PoolSwapLibrary": "0x542848e66d8f387a78717be7b39f7259b7782bae" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_pool","type":"address"},{"indexed":true,"internalType":"address","name":"keeper","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"KeeperPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_pool","type":"address"},{"indexed":true,"internalType":"address","name":"keeper","type":"address"},{"indexed":false,"internalType":"uint256","name":"expectedReward","type":"uint256"}],"name":"KeeperPaymentError","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"poolAddress","type":"address"},{"indexed":true,"internalType":"int256","name":"firstPrice","type":"int256"}],"name":"PoolAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"PoolUpkeepError","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":true,"internalType":"int256","name":"startPrice","type":"int256"},{"indexed":true,"internalType":"int256","name":"endPrice","type":"int256"}],"name":"UpkeepSuccessful","type":"event"},{"inputs":[],"name":"BASE_TIP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BLOCK_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIP_DELTA_PER_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_pools","type":"address[]"}],"name":"checkUpkeepMultiplePools","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"checkUpkeepSinglePool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"executionPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IPoolFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"uint256","name":"_gasPrice","type":"uint256"},{"internalType":"uint256","name":"_gasSpent","type":"uint256"}],"name":"keeperGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"uint256","name":"_gasPrice","type":"uint256"},{"internalType":"uint256","name":"_gasSpent","type":"uint256"},{"internalType":"uint256","name":"_savedPreviousUpdatedTimestamp","type":"uint256"},{"internalType":"uint256","name":"_poolInterval","type":"uint256"}],"name":"keeperReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_savedPreviousUpdatedTimestamp","type":"uint256"},{"internalType":"uint256","name":"_poolInterval","type":"uint256"}],"name":"keeperTip","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"}],"name":"newPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"}],"name":"performUpkeepMultiplePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"performUpkeepSinglePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"name":"setFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"setGasPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040526402540be4006003553480156200001a57600080fd5b50604051620020d5380380620020d58339810160408190526200003d9162000119565b6200004833620000c9565b6001600160a01b038116620000a35760405162461bcd60e51b815260206004820152601b60248201527f466163746f72792063616e6e6f74206265203020616464726573730000000000604482015260640160405180910390fd5b600280546001600160a01b0319166001600160a01b03929092169190911790556200014b565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156200012c57600080fd5b81516001600160a01b03811681146200014457600080fd5b9392505050565b611f7a806200015b6000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c8063b3fbb7c4116100ad578063ce1dcdfc11610071578063ce1dcdfc1461025e578063f2fde38b14610271578063f930191014610284578063fcab9e981461028c578063fe173b971461029f57600080fd5b8063b3fbb7c4146101f2578063b9c6536514610205578063bf1fe42014610218578063c45a01551461022b578063cdd9e1371461023e57600080fd5b80638da5cb5b116100f45780638da5cb5b1461019f57806391a60782146101c45780639f9a3d95146101d7578063a40d6b80146101df578063aea8acb1146101d757600080fd5b80630417cf8e14610131578063225739b11461014c5780633c5c7fb31461016f5780635bb4780814610184578063715018a614610197575b600080fd5b610139601281565b6040519081526020015b60405180910390f35b61015f61015a366004611a4c565b6102a8565b6040519015158152602001610143565b61018261017d366004611a4c565b6103a9565b005b610182610192366004611a4c565b6105b7565b610182610603565b6000546001600160a01b03165b6040516001600160a01b039091168152602001610143565b6101826101d2366004611a4c565b610639565b610139600581565b6101396101ed366004611a86565b61083b565b610139610200366004611abb565b610988565b610139610213366004611c7a565b610b72565b610182610226366004611c61565b610bce565b6002546101ac906001600160a01b031681565b61013961024c366004611a4c565b60016020526000908152604090205481565b61015f61026c366004611aff565b610bfd565b61018261027f366004611a4c565b610c5e565b610139600d81565b61018261029a366004611aff565b610cf9565b61013960035481565b600254604051635ab78ee160e01b81526001600160a01b0383811660048301526000921690635ab78ee19060240160206040518083038186803b1580156102ee57600080fd5b505afa158015610302573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103269190611b74565b61033257506000919050565b816001600160a01b0316637bbf10336040518163ffffffff1660e01b815260040160206040518083038186803b15801561036b57600080fd5b505afa15801561037f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a39190611b74565b92915050565b6002546001600160a01b031633146103fd5760405162461bcd60e51b815260206004820152601260248201527143616c6c6572206e6f7420666163746f727960701b60448201526064015b60405180910390fd5b6000816001600160a01b031663b9ed8abf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561043857600080fd5b505afa15801561044c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104709190611a69565b90506000816001600160a01b03166398d5fdca6040518163ffffffff1660e01b815260040160206040518083038186803b1580156104ad57600080fd5b505afa1580156104c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e59190611b96565b9050600081136105375760405162461bcd60e51b815260206004820152601b60248201527f4669727374207072696365206973206e6f6e2d706f736974697665000000000060448201526064016103f4565b600061055d61055861054884610d45565b668075782dace9d960c71b610dd3565b611050565b905081846001600160a01b03167fe950cb32f7a787627d713d7365623fef2d762ef8fcf813b865a04350852deb9b60405160405180910390a36001600160a01b039093166000908152600160205260409020929092555050565b6000546001600160a01b031633146105e15760405162461bcd60e51b81526004016103f490611cfe565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461062d5760405162461bcd60e51b81526004016103f490611cfe565b61063760006110f7565b565b60005a9050610647826102a8565b61064f575050565b6000829050600080600080846001600160a01b03166304883c276040518163ffffffff1660e01b815260040160006040518083038186803b15801561069357600080fd5b505afa1580156106a7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106cf9190810190611baf565b6001600160a01b038b81166000908152600160205260409081902080549087905590516303d8ce9d60e61b81526004810182905260248101879052959950939750919550935090919087169063f633a74090604401600060405180830381600087803b15801561073e57600080fd5b505af192505050801561074f575060015b6107ce5761075b611e89565b806308c379a014156107c25750610770611ea5565b8061077b57506107c4565b886001600160a01b03167f8a47468bf96478429d382ed6385d9c77fba8b89540cd88199b1b51d5723b11fa826040516107b49190611ceb565b60405180910390a250610831565b505b3d6000803e3d6000fd5b60005a6107db9089611d8c565b90506107ec89600354838787611147565b85828a6001600160a01b03167f0aa8d2838ad6d4e2a5d7ca0826dfdbc36d922adf8fe5c6d25aee2724b07de074886040516108279190611ceb565b60405180910390a4505b5050505050505050565b600080846001600160a01b0316638226f3966040518163ffffffff1660e01b815260040160206040518083038186803b15801561087757600080fd5b505afa15801561088b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108af9190611a69565b6001600160a01b03166398d5fdca6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108e757600080fd5b505afa1580156108fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091f9190611b96565b905060008113610933576000915050610981565b60006109476109428587611d6d565b61126c565b905060006109548361126c565b905061097b6109766109668484610dd3565b668075782dace9d960c71b6112d0565b611566565b93505050505b9392505050565b60008061099687878761083b565b905060006109a76109428686610b72565b90506109bc816109b7606461126c565b6112d0565b905060006109e96105586109cf8561126c565b6109e46109666109de8861126c565b87610dd3565b6115e9565b90506000896001600160a01b031663217a4b706040518163ffffffff1660e01b815260040160206040518083038186803b158015610a2657600080fd5b505afa158015610a3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5e9190611a69565b6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610a9657600080fd5b505afa158015610aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ace9190611c9c565b60405163bf36f0e960e01b81526004810184905260ff9190911660248201819052915060009073542848e66d8f387a78717be7b39f7259b7782bae9063bf36f0e99060440160206040518083038186803b158015610b2b57600080fd5b505af4158015610b3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b639190611b96565b9b9a5050505050505050505050565b600080610b7f8385611d33565b610b899042611d8c565b90506000600d610b9a836005611d6d565b610ba49190611d4b565b610baf906005611d33565b90506064811115610bc5576064925050506103a3565b91506103a39050565b6000546001600160a01b03163314610bf85760405162461bcd60e51b81526004016103f490611cfe565b600355565b6000805b82811015610c5457610c33848483818110610c1e57610c1e611e5d565b905060200201602081019061015a9190611a4c565b15610c425760019150506103a3565b80610c4c81611e00565b915050610c01565b5060009392505050565b6000546001600160a01b03163314610c885760405162461bcd60e51b81526004016103f490611cfe565b6001600160a01b038116610ced5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103f4565b610cf6816110f7565b50565b60005b81811015610d4057610d2e838383818110610d1957610d19611e5d565b90506020020160208101906101d29190611a4c565b80610d3881611e00565b915050610cfc565b505050565b600081610d5457506000919050565b6000808313610d665782600003610d68565b825b90506000610d75826119a9565b90506070811015610d8e578060700382901b9150610da1565b6070811115610da1576070810382901c91505b6001600160701b03909116613fff820160701b17906000841215610dc9576001607f1b821791505b5060801b92915050565b6000617fff60f084811c8216919084901c811690821415610e835780617fff1415610e51576001600160801b03198581169085161415610e1e57505050600160ff1b811682186103a3565b600160ff1b6001600160801b0319868618161415610e41575050508181176103a3565b5061ffff60ef1b91506103a39050565b600160801b600160ff1b038416610e72575061ffff60ef1b91506103a39050565b505050600160ff1b811682186103a3565b80617fff1415610ebf57600160801b600160ff1b038516610eae575061ffff60ef1b91506103a39050565b505050600160ff1b821681186103a3565b6001600160701b03608086901c1682610edb5760019250610ee2565b600160701b175b6001600160701b03608086901c1682610efe5760019250610f05565b600160701b175b9081029081610f3357600160ff1b87871816610f22576000610f28565b600160ff1b5b9450505050506103a3565b928201926000600160e11b831015610f6657600160e01b831015610f5f57610f5a836119a9565b610f69565b60e0610f69565b60e15b90506140708186011015610f84576000945060009250611021565b6140e08186011015610fc757614070851015610fa957846140700383901c9250610fbe565b614070851115610fbe57614070850383901b92505b60009450611021565b61c0dd8186011115610fe157617fff945060009250611021565b6070811115610ff8576070810383901c925061100b565b607081101561100b578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6001600160801b0316171760801b955050505050506103a3565b6000617fff60f083901c166140fe81111561106a57600080fd5b613fff81101561107d5750600092915050565b600160701b6001600160701b03608085901c161761406f8210156110a75761406f8290031c6110b9565b61406f8211156110b95761406e1982011b5b6001607f1b608085901c106110e357600160ff1b8111156110d957600080fd5b6000039392505050565b6001600160ff1b0381111561098157600080fd5b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006111568686868686610988565b604051636dc2b27160e01b8152336004820152602481018290529091506001600160a01b03871690636dc2b27190604401602060405180830381600087803b1580156111a157600080fd5b505af11580156111b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d99190611b74565b156112235760405181815233906001600160a01b038816907ff03012dd4aab142682aa01439f94e975e2ec77ef558352323bc05f382f74b0829060200160405180910390a3611264565b60405181815233906001600160a01b038816907f08b35d4c86707ba44cdcc5efaa79b8a307e6c7f789f1eb86ca1ff1e9bde056979060200160405180910390a35b505050505050565b60008161127b57506000919050565b816000611287826119a9565b905060708110156112a0578060700382901b91506112b3565b60708111156112b3576070810382901c91505b613fff0160701b6001600160701b03919091161760801b92915050565b6000617fff60f084811c8216919084901c8116908214156113055780617fff1415610e72575061ffff60ef1b91506103a39050565b80617fff1415611349576dffffffffffffffffffffffffffff60801b841615611338575061ffff60ef1b91506103a39050565b505050808218600160ff1b166103a3565b600160801b600160ff1b03841661139357600160801b600160ff1b03851661137b575061ffff60ef1b91506103a39050565b505050808218600160ff1b16617fff60f01b176103a3565b6001600160701b03608085901c16816113af57600191506113b6565b600160701b175b6001600160701b03608087901c16836113f55780156113f05760006113da826119a9565b6001955060e20393840160711901939190911b90505b6113ff565b600160701b1760721b5b81818161140e5761140e611e47565b0490508061142a57600160ff1b87871816610f22576000610f28565b6001606c1b81101561143e5761143e611e1b565b6000600160731b82101561147d57600160721b82101561147257600160711b82101561146b576070611475565b6071611475565b60725b60ff16611486565b611486826119a9565b9050836140710181860111156114a457617fff945060009150611537565b83818601613ffc0110156114bf576000945060009150611537565b83818601613f8c01101561150c578385613ffc0111156114ea578385613ffc010382901b9150611503565b8385613ffc01101561150357613ffc8585030382901c91505b60009450611537565b607081111561151f576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6001600160801b0316171760801b955050505050506103a3565b6000617fff60f083901c16613fff8110156115845750600092915050565b6001607f1b608084901c1061159857600080fd5b6140fe8111156115a757600080fd5b600160701b6001600160701b03608085901c161761406f8210156115d15761406f8290031c610981565b61406f8211156109815761406e1982011b9392505050565b6000617fff60f084811c8216919084901c8116908214156116375780617fff141561162d576001600160801b03198581169085161415610e415784925050506103a3565b84925050506103a3565b80617fff141561164b5783925050506103a3565b6001607f1b608086901c90811015906001600160701b0316836116715760019350611678565b600160701b175b6001607f1b608087901c90811015906001600160701b03168461169e57600194506116a5565b600160701b175b826116d5576001600160801b03198816600160ff1b146116c557876116c8565b60005b96505050505050506103a3565b806116f5576001600160801b03198916600160ff1b146116c557886116c8565b848603841515831515141561180057607081131561171c57899750505050505050506103a3565b600081131561172e5790811c9061175d565b606f1981121561174757889750505050505050506103a3565b600081121561175d578060000384901c93508596505b92810192600160711b8410611778576001968701969390931c925b86617fff14156117aa578461179257617fff60f01b61179c565b6001600160f01b03195b9750505050505050506103a3565b600160701b8410156117bf57600096506117cc565b6001600160701b03841693505b83607088901b866117de5760006117e4565b6001607f1b5b6001600160801b0316171760801b9750505050505050506103a3565b600081131561181b57600184901b9350600187039650611832565b600081121561183257600182901b91506001860396505b60708113156118445760019150611891565b6001811315611861576001810360018303901c6001019150611891565b606f198112156118745760019350611891565b600019811215611891576001816000030360018503901c60010193505b8184106118a25781840393506118ab565b83820393508294505b836118c15750600096506103a395505050505050565b60006118cc856119a9565b905080607114156118f257600185901c6001600160701b03169450600188019750611941565b607081101561193457607081900380891115611921578086901b6001600160701b03169550808903985061192e565b600098600019019590951b945b50611941565b6001600160701b03851694505b87617fff1415611974578561195b57617fff60f01b611965565b6001600160f01b03195b985050505050505050506103a3565b84607089901b8761198657600061198c565b6001607f1b5b6001600160801b0316171760801b985050505050505050506103a3565b60008082116119b757600080fd5b6000600160801b83106119cc57608092831c92015b6801000000000000000083106119e457604092831c92015b64010000000083106119f857602092831c92015b620100008310611a0a57601092831c92015b6101008310611a1b57600892831c92015b60108310611a2b57600492831c92015b60048310611a3b57600292831c92015b600283106103a35760010192915050565b600060208284031215611a5e57600080fd5b813561098181611f2f565b600060208284031215611a7b57600080fd5b815161098181611f2f565b600080600060608486031215611a9b57600080fd5b8335611aa681611f2f565b95602085013595506040909401359392505050565b600080600080600060a08688031215611ad357600080fd5b8535611ade81611f2f565b97602087013597506040870135966060810135965060800135945092505050565b60008060208385031215611b1257600080fd5b823567ffffffffffffffff80821115611b2a57600080fd5b818501915085601f830112611b3e57600080fd5b813581811115611b4d57600080fd5b8660208260051b8501011115611b6257600080fd5b60209290920196919550909350505050565b600060208284031215611b8657600080fd5b8151801515811461098157600080fd5b600060208284031215611ba857600080fd5b5051919050565b60008060008060808587031215611bc557600080fd5b84519350602085015167ffffffffffffffff80821115611be457600080fd5b818701915087601f830112611bf857600080fd5b815181811115611c0a57611c0a611e73565b6040519150611c23601f8201601f191660200183611dd3565b808252886020828501011115611c3857600080fd5b611c49816020840160208601611da3565b50604087015160609097015195989097509350505050565b600060208284031215611c7357600080fd5b5035919050565b60008060408385031215611c8d57600080fd5b50508035926020909101359150565b600060208284031215611cae57600080fd5b815160ff8116811461098157600080fd5b60008151808452611cd7816020860160208601611da3565b601f01601f19169290920160200192915050565b6020815260006109816020830184611cbf565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60008219821115611d4657611d46611e31565b500190565b600082611d6857634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615611d8757611d87611e31565b500290565b600082821015611d9e57611d9e611e31565b500390565b60005b83811015611dbe578181015183820152602001611da6565b83811115611dcd576000848401525b50505050565b601f8201601f1916810167ffffffffffffffff81118282101715611df957611df9611e73565b6040525050565b6000600019821415611e1457611e14611e31565b5060010190565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d1115611ea25760046000803e5060005160e01c5b90565b600060443d1015611eb35790565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715611ee357505050505090565b8285019150815181811115611efb5750505050505090565b843d8701016020828501011115611f155750505050505090565b611f2460208286010187611dd3565b509095945050505050565b6001600160a01b0381168114610cf657600080fdfea26469706673582212202e1a80ff10a4c06d30d3b609f5014ec1b01c0a9cbd27f0aab71c3a5b7c2a996264736f6c6343000807003300000000000000000000000098c58c1ceb01e198f8356763d5cba8eb7b11e4e2
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061012c5760003560e01c8063b3fbb7c4116100ad578063ce1dcdfc11610071578063ce1dcdfc1461025e578063f2fde38b14610271578063f930191014610284578063fcab9e981461028c578063fe173b971461029f57600080fd5b8063b3fbb7c4146101f2578063b9c6536514610205578063bf1fe42014610218578063c45a01551461022b578063cdd9e1371461023e57600080fd5b80638da5cb5b116100f45780638da5cb5b1461019f57806391a60782146101c45780639f9a3d95146101d7578063a40d6b80146101df578063aea8acb1146101d757600080fd5b80630417cf8e14610131578063225739b11461014c5780633c5c7fb31461016f5780635bb4780814610184578063715018a614610197575b600080fd5b610139601281565b6040519081526020015b60405180910390f35b61015f61015a366004611a4c565b6102a8565b6040519015158152602001610143565b61018261017d366004611a4c565b6103a9565b005b610182610192366004611a4c565b6105b7565b610182610603565b6000546001600160a01b03165b6040516001600160a01b039091168152602001610143565b6101826101d2366004611a4c565b610639565b610139600581565b6101396101ed366004611a86565b61083b565b610139610200366004611abb565b610988565b610139610213366004611c7a565b610b72565b610182610226366004611c61565b610bce565b6002546101ac906001600160a01b031681565b61013961024c366004611a4c565b60016020526000908152604090205481565b61015f61026c366004611aff565b610bfd565b61018261027f366004611a4c565b610c5e565b610139600d81565b61018261029a366004611aff565b610cf9565b61013960035481565b600254604051635ab78ee160e01b81526001600160a01b0383811660048301526000921690635ab78ee19060240160206040518083038186803b1580156102ee57600080fd5b505afa158015610302573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103269190611b74565b61033257506000919050565b816001600160a01b0316637bbf10336040518163ffffffff1660e01b815260040160206040518083038186803b15801561036b57600080fd5b505afa15801561037f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a39190611b74565b92915050565b6002546001600160a01b031633146103fd5760405162461bcd60e51b815260206004820152601260248201527143616c6c6572206e6f7420666163746f727960701b60448201526064015b60405180910390fd5b6000816001600160a01b031663b9ed8abf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561043857600080fd5b505afa15801561044c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104709190611a69565b90506000816001600160a01b03166398d5fdca6040518163ffffffff1660e01b815260040160206040518083038186803b1580156104ad57600080fd5b505afa1580156104c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e59190611b96565b9050600081136105375760405162461bcd60e51b815260206004820152601b60248201527f4669727374207072696365206973206e6f6e2d706f736974697665000000000060448201526064016103f4565b600061055d61055861054884610d45565b668075782dace9d960c71b610dd3565b611050565b905081846001600160a01b03167fe950cb32f7a787627d713d7365623fef2d762ef8fcf813b865a04350852deb9b60405160405180910390a36001600160a01b039093166000908152600160205260409020929092555050565b6000546001600160a01b031633146105e15760405162461bcd60e51b81526004016103f490611cfe565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461062d5760405162461bcd60e51b81526004016103f490611cfe565b61063760006110f7565b565b60005a9050610647826102a8565b61064f575050565b6000829050600080600080846001600160a01b03166304883c276040518163ffffffff1660e01b815260040160006040518083038186803b15801561069357600080fd5b505afa1580156106a7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106cf9190810190611baf565b6001600160a01b038b81166000908152600160205260409081902080549087905590516303d8ce9d60e61b81526004810182905260248101879052959950939750919550935090919087169063f633a74090604401600060405180830381600087803b15801561073e57600080fd5b505af192505050801561074f575060015b6107ce5761075b611e89565b806308c379a014156107c25750610770611ea5565b8061077b57506107c4565b886001600160a01b03167f8a47468bf96478429d382ed6385d9c77fba8b89540cd88199b1b51d5723b11fa826040516107b49190611ceb565b60405180910390a250610831565b505b3d6000803e3d6000fd5b60005a6107db9089611d8c565b90506107ec89600354838787611147565b85828a6001600160a01b03167f0aa8d2838ad6d4e2a5d7ca0826dfdbc36d922adf8fe5c6d25aee2724b07de074886040516108279190611ceb565b60405180910390a4505b5050505050505050565b600080846001600160a01b0316638226f3966040518163ffffffff1660e01b815260040160206040518083038186803b15801561087757600080fd5b505afa15801561088b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108af9190611a69565b6001600160a01b03166398d5fdca6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108e757600080fd5b505afa1580156108fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091f9190611b96565b905060008113610933576000915050610981565b60006109476109428587611d6d565b61126c565b905060006109548361126c565b905061097b6109766109668484610dd3565b668075782dace9d960c71b6112d0565b611566565b93505050505b9392505050565b60008061099687878761083b565b905060006109a76109428686610b72565b90506109bc816109b7606461126c565b6112d0565b905060006109e96105586109cf8561126c565b6109e46109666109de8861126c565b87610dd3565b6115e9565b90506000896001600160a01b031663217a4b706040518163ffffffff1660e01b815260040160206040518083038186803b158015610a2657600080fd5b505afa158015610a3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5e9190611a69565b6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610a9657600080fd5b505afa158015610aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ace9190611c9c565b60405163bf36f0e960e01b81526004810184905260ff9190911660248201819052915060009073542848e66d8f387a78717be7b39f7259b7782bae9063bf36f0e99060440160206040518083038186803b158015610b2b57600080fd5b505af4158015610b3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b639190611b96565b9b9a5050505050505050505050565b600080610b7f8385611d33565b610b899042611d8c565b90506000600d610b9a836005611d6d565b610ba49190611d4b565b610baf906005611d33565b90506064811115610bc5576064925050506103a3565b91506103a39050565b6000546001600160a01b03163314610bf85760405162461bcd60e51b81526004016103f490611cfe565b600355565b6000805b82811015610c5457610c33848483818110610c1e57610c1e611e5d565b905060200201602081019061015a9190611a4c565b15610c425760019150506103a3565b80610c4c81611e00565b915050610c01565b5060009392505050565b6000546001600160a01b03163314610c885760405162461bcd60e51b81526004016103f490611cfe565b6001600160a01b038116610ced5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103f4565b610cf6816110f7565b50565b60005b81811015610d4057610d2e838383818110610d1957610d19611e5d565b90506020020160208101906101d29190611a4c565b80610d3881611e00565b915050610cfc565b505050565b600081610d5457506000919050565b6000808313610d665782600003610d68565b825b90506000610d75826119a9565b90506070811015610d8e578060700382901b9150610da1565b6070811115610da1576070810382901c91505b6001600160701b03909116613fff820160701b17906000841215610dc9576001607f1b821791505b5060801b92915050565b6000617fff60f084811c8216919084901c811690821415610e835780617fff1415610e51576001600160801b03198581169085161415610e1e57505050600160ff1b811682186103a3565b600160ff1b6001600160801b0319868618161415610e41575050508181176103a3565b5061ffff60ef1b91506103a39050565b600160801b600160ff1b038416610e72575061ffff60ef1b91506103a39050565b505050600160ff1b811682186103a3565b80617fff1415610ebf57600160801b600160ff1b038516610eae575061ffff60ef1b91506103a39050565b505050600160ff1b821681186103a3565b6001600160701b03608086901c1682610edb5760019250610ee2565b600160701b175b6001600160701b03608086901c1682610efe5760019250610f05565b600160701b175b9081029081610f3357600160ff1b87871816610f22576000610f28565b600160ff1b5b9450505050506103a3565b928201926000600160e11b831015610f6657600160e01b831015610f5f57610f5a836119a9565b610f69565b60e0610f69565b60e15b90506140708186011015610f84576000945060009250611021565b6140e08186011015610fc757614070851015610fa957846140700383901c9250610fbe565b614070851115610fbe57614070850383901b92505b60009450611021565b61c0dd8186011115610fe157617fff945060009250611021565b6070811115610ff8576070810383901c925061100b565b607081101561100b578060700383901b92505b6001600160701b03831692506140df8186010394505b82607086901b888a186001607f1b60801b1660801c6001600160801b0316171760801b955050505050506103a3565b6000617fff60f083901c166140fe81111561106a57600080fd5b613fff81101561107d5750600092915050565b600160701b6001600160701b03608085901c161761406f8210156110a75761406f8290031c6110b9565b61406f8211156110b95761406e1982011b5b6001607f1b608085901c106110e357600160ff1b8111156110d957600080fd5b6000039392505050565b6001600160ff1b0381111561098157600080fd5b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006111568686868686610988565b604051636dc2b27160e01b8152336004820152602481018290529091506001600160a01b03871690636dc2b27190604401602060405180830381600087803b1580156111a157600080fd5b505af11580156111b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d99190611b74565b156112235760405181815233906001600160a01b038816907ff03012dd4aab142682aa01439f94e975e2ec77ef558352323bc05f382f74b0829060200160405180910390a3611264565b60405181815233906001600160a01b038816907f08b35d4c86707ba44cdcc5efaa79b8a307e6c7f789f1eb86ca1ff1e9bde056979060200160405180910390a35b505050505050565b60008161127b57506000919050565b816000611287826119a9565b905060708110156112a0578060700382901b91506112b3565b60708111156112b3576070810382901c91505b613fff0160701b6001600160701b03919091161760801b92915050565b6000617fff60f084811c8216919084901c8116908214156113055780617fff1415610e72575061ffff60ef1b91506103a39050565b80617fff1415611349576dffffffffffffffffffffffffffff60801b841615611338575061ffff60ef1b91506103a39050565b505050808218600160ff1b166103a3565b600160801b600160ff1b03841661139357600160801b600160ff1b03851661137b575061ffff60ef1b91506103a39050565b505050808218600160ff1b16617fff60f01b176103a3565b6001600160701b03608085901c16816113af57600191506113b6565b600160701b175b6001600160701b03608087901c16836113f55780156113f05760006113da826119a9565b6001955060e20393840160711901939190911b90505b6113ff565b600160701b1760721b5b81818161140e5761140e611e47565b0490508061142a57600160ff1b87871816610f22576000610f28565b6001606c1b81101561143e5761143e611e1b565b6000600160731b82101561147d57600160721b82101561147257600160711b82101561146b576070611475565b6071611475565b60725b60ff16611486565b611486826119a9565b9050836140710181860111156114a457617fff945060009150611537565b83818601613ffc0110156114bf576000945060009150611537565b83818601613f8c01101561150c578385613ffc0111156114ea578385613ffc010382901b9150611503565b8385613ffc01101561150357613ffc8585030382901c91505b60009450611537565b607081111561151f576070810382901c91505b6001600160701b038216915083818601613f8d010394505b81607086901b888a186001607f1b60801b1660801c6001600160801b0316171760801b955050505050506103a3565b6000617fff60f083901c16613fff8110156115845750600092915050565b6001607f1b608084901c1061159857600080fd5b6140fe8111156115a757600080fd5b600160701b6001600160701b03608085901c161761406f8210156115d15761406f8290031c610981565b61406f8211156109815761406e1982011b9392505050565b6000617fff60f084811c8216919084901c8116908214156116375780617fff141561162d576001600160801b03198581169085161415610e415784925050506103a3565b84925050506103a3565b80617fff141561164b5783925050506103a3565b6001607f1b608086901c90811015906001600160701b0316836116715760019350611678565b600160701b175b6001607f1b608087901c90811015906001600160701b03168461169e57600194506116a5565b600160701b175b826116d5576001600160801b03198816600160ff1b146116c557876116c8565b60005b96505050505050506103a3565b806116f5576001600160801b03198916600160ff1b146116c557886116c8565b848603841515831515141561180057607081131561171c57899750505050505050506103a3565b600081131561172e5790811c9061175d565b606f1981121561174757889750505050505050506103a3565b600081121561175d578060000384901c93508596505b92810192600160711b8410611778576001968701969390931c925b86617fff14156117aa578461179257617fff60f01b61179c565b6001600160f01b03195b9750505050505050506103a3565b600160701b8410156117bf57600096506117cc565b6001600160701b03841693505b83607088901b866117de5760006117e4565b6001607f1b5b6001600160801b0316171760801b9750505050505050506103a3565b600081131561181b57600184901b9350600187039650611832565b600081121561183257600182901b91506001860396505b60708113156118445760019150611891565b6001811315611861576001810360018303901c6001019150611891565b606f198112156118745760019350611891565b600019811215611891576001816000030360018503901c60010193505b8184106118a25781840393506118ab565b83820393508294505b836118c15750600096506103a395505050505050565b60006118cc856119a9565b905080607114156118f257600185901c6001600160701b03169450600188019750611941565b607081101561193457607081900380891115611921578086901b6001600160701b03169550808903985061192e565b600098600019019590951b945b50611941565b6001600160701b03851694505b87617fff1415611974578561195b57617fff60f01b611965565b6001600160f01b03195b985050505050505050506103a3565b84607089901b8761198657600061198c565b6001607f1b5b6001600160801b0316171760801b985050505050505050506103a3565b60008082116119b757600080fd5b6000600160801b83106119cc57608092831c92015b6801000000000000000083106119e457604092831c92015b64010000000083106119f857602092831c92015b620100008310611a0a57601092831c92015b6101008310611a1b57600892831c92015b60108310611a2b57600492831c92015b60048310611a3b57600292831c92015b600283106103a35760010192915050565b600060208284031215611a5e57600080fd5b813561098181611f2f565b600060208284031215611a7b57600080fd5b815161098181611f2f565b600080600060608486031215611a9b57600080fd5b8335611aa681611f2f565b95602085013595506040909401359392505050565b600080600080600060a08688031215611ad357600080fd5b8535611ade81611f2f565b97602087013597506040870135966060810135965060800135945092505050565b60008060208385031215611b1257600080fd5b823567ffffffffffffffff80821115611b2a57600080fd5b818501915085601f830112611b3e57600080fd5b813581811115611b4d57600080fd5b8660208260051b8501011115611b6257600080fd5b60209290920196919550909350505050565b600060208284031215611b8657600080fd5b8151801515811461098157600080fd5b600060208284031215611ba857600080fd5b5051919050565b60008060008060808587031215611bc557600080fd5b84519350602085015167ffffffffffffffff80821115611be457600080fd5b818701915087601f830112611bf857600080fd5b815181811115611c0a57611c0a611e73565b6040519150611c23601f8201601f191660200183611dd3565b808252886020828501011115611c3857600080fd5b611c49816020840160208601611da3565b50604087015160609097015195989097509350505050565b600060208284031215611c7357600080fd5b5035919050565b60008060408385031215611c8d57600080fd5b50508035926020909101359150565b600060208284031215611cae57600080fd5b815160ff8116811461098157600080fd5b60008151808452611cd7816020860160208601611da3565b601f01601f19169290920160200192915050565b6020815260006109816020830184611cbf565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60008219821115611d4657611d46611e31565b500190565b600082611d6857634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615611d8757611d87611e31565b500290565b600082821015611d9e57611d9e611e31565b500390565b60005b83811015611dbe578181015183820152602001611da6565b83811115611dcd576000848401525b50505050565b601f8201601f1916810167ffffffffffffffff81118282101715611df957611df9611e73565b6040525050565b6000600019821415611e1457611e14611e31565b5060010190565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d1115611ea25760046000803e5060005160e01c5b90565b600060443d1015611eb35790565b6040516003193d81016004833e81513d67ffffffffffffffff8160248401118184111715611ee357505050505090565b8285019150815181811115611efb5750505050505090565b843d8701016020828501011115611f155750505050505090565b611f2460208286010187611dd3565b509095945050505050565b6001600160a01b0381168114610cf657600080fdfea26469706673582212202e1a80ff10a4c06d30d3b609f5014ec1b01c0a9cbd27f0aab71c3a5b7c2a996264736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000098c58c1ceb01e198f8356763d5cba8eb7b11e4e2
-----Decoded View---------------
Arg [0] : _factory (address): 0x98C58c1cEb01E198F8356763d5CbA8EB7b11e4E2
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000098c58c1ceb01e198f8356763d5cba8eb7b11e4e2
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.