Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
StableBPTOracle
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT /* ██████╗ ██╗ ██╗ ██╗███████╗██████╗ ███████╗██████╗ ██████╗ ██╗ ██╗ ██╔══██╗██║ ██║ ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝ ██████╔╝██║ ██║ ██║█████╗ ██████╔╝█████╗ ██████╔╝██████╔╝ ╚████╔╝ ██╔══██╗██║ ██║ ██║██╔══╝ ██╔══██╗██╔══╝ ██╔══██╗██╔══██╗ ╚██╔╝ ██████╔╝███████╗╚██████╔╝███████╗██████╔╝███████╗██║ ██║██║ ██║ ██║ ╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ */ pragma solidity 0.8.22; import { FixedPoint } from "../libraries/balancer-v2/FixedPoint.sol"; import { VaultReentrancyLib } from "../libraries/balancer-v2/VaultReentrancyLib.sol"; import "../utils/BlueberryErrors.sol" as Errors; import { UsingBaseOracle } from "./UsingBaseOracle.sol"; import { IBaseOracle } from "../interfaces/IBaseOracle.sol"; import { IBalancerV2StablePool } from "../interfaces/balancer-v2/IBalancerV2StablePool.sol"; import { IBalancerVault } from "../interfaces/balancer-v2/IBalancerVault.sol"; import { IRateProvider } from "../interfaces/balancer-v2/IRateProvider.sol"; /** * @title StableBPTOracle * @author BlueberryProtocol * @notice Oracle contract which privides price feeds of Stable Balancer LP tokens */ contract StableBPTOracle is IBaseOracle, UsingBaseOracle { using FixedPoint for uint256; /*////////////////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////////////////*/ /** * @dev Struct to store token info related to Balancer Pool tokens * @param tokens An array of tokens within the pool * @param rateProviders An array of rate providers associated with the tokens in the pool */ struct TokenInfo { address[] tokens; address[] rateProviders; } /*////////////////////////////////////////////////////////////////////////// STORAGE //////////////////////////////////////////////////////////////////////////*/ /// @dev Address of the weighted pool oracle IBaseOracle private _weightedPoolOracle; /// @dev Address of the Balancer Vault IBalancerVault private _vault; /// @dev mapping of registered bpt tokens to their token info mapping(address => TokenInfo) private _tokenInfo; /*////////////////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////////////////*/ // Protects the oracle from being manipulated via read-only reentrancy modifier balancerNonReentrant() { VaultReentrancyLib.ensureNotInVaultContext(_vault); _; } /*////////////////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////////////////*/ /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /*////////////////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /** * @notice Initializes the contract * @param vault Instance of the Balancer V2 Vault * @param base The base oracle instance. * @param owner Address of the owner of the contract. */ function initialize(IBalancerVault vault, IBaseOracle base, address owner) external initializer { __UsingBaseOracle_init(base, owner); _vault = vault; } /// @inheritdoc IBaseOracle function getPrice(address token) public override balancerNonReentrant returns (uint256) { TokenInfo memory tokenInfo = getBptInfo(token); uint256 tokenLength = tokenInfo.tokens.length; if (tokenLength == 0) revert Errors.ORACLE_NOT_SUPPORT_LP(token); uint256 minPrice = _getTokensMinPrice(tokenInfo.tokens, tokenInfo.rateProviders, tokenLength); uint256 rate = IBalancerV2StablePool(token).getRate(); return minPrice.mulDown(rate); } /** * @notice Register Balancer Pool token to oracle * @dev Stores persistent data of Balancer Pool token * @dev An oracle cannot be used for a LP token unless it is registered * @param bpt Address of the Balancer Pool token to register */ function registerBpt(address bpt) external onlyOwner { if (bpt == address(0)) revert Errors.ZERO_ADDRESS(); IBalancerV2StablePool pool = IBalancerV2StablePool(bpt); (address[] memory tokens, , ) = _vault.getPoolTokens(pool.getPoolId()); address[] memory rateProviders = pool.getRateProviders(); uint256 tokenLength = tokens.length; // Only ComposableStablePools return BPT within the array of tokens when calling `getPoolTokens`. // In order to support all types of stable pools we need to encapsulate `getBPTIndex` // in a try/catch block. If the pool is not a ComposableStablePool, we will just // set the subTokens to the tokens array that we queried from the vault try pool.getBptIndex() returns (uint256 bptIndex) { address[] memory subTokens = new address[](tokenLength - 1); address[] memory subRateProviders = new address[](tokenLength - 1); uint256 index = 0; for (uint256 i = 0; i < tokenLength; ++i) { if (i != bptIndex) { subTokens[index] = tokens[i]; subRateProviders[index] = rateProviders[i]; index++; } } _tokenInfo[bpt] = TokenInfo(subTokens, subRateProviders); } catch { _tokenInfo[bpt] = TokenInfo(tokens, rateProviders); } emit RegisterLpToken(bpt); } /** * @notice Set the weighted pool oracle * @dev Only owner can set the weighted pool oracle * @param oracle Address of the oracle to set as the weighted pool oracle */ function setWeightedPoolOracle(address oracle) external onlyOwner { if (oracle == address(0)) revert Errors.ZERO_ADDRESS(); _weightedPoolOracle = IBaseOracle(oracle); } /** * @notice Fetches the TokenInfo struct of a given LP token * @param bpt Balancer Pool Token address * @return TokenInfo struct of given LP token */ function getBptInfo(address bpt) public view returns (TokenInfo memory) { return _tokenInfo[bpt]; } /// @notice Returns the weighted pool oracle address function getWeightedPoolOracle() external view returns (address) { return address(_weightedPoolOracle); } /** * @notice Returns the minimum price of a given array of tokens * @param tokens An array of tokens within the pool * @param rateProviders An array of rate providers associated with the tokens in the pool * @param length The length of the array of tokens * @return The minimum price of the given array of tokens */ function _getTokensMinPrice( address[] memory tokens, address[] memory rateProviders, uint256 length ) internal returns (uint256) { uint256 minPrice; address minToken; for (uint256 i = 0; i < length; ++i) { address minCandidate = tokens[i]; IRateProvider rateProvider = IRateProvider(rateProviders[i]); uint256 minCandidatePrice = _calculateMinCandidatePrice(rateProvider, minCandidate); if (minCandidatePrice < minPrice || i == 0) { minToken = minCandidate; minPrice = minCandidatePrice; } } return minPrice; } /** * @notice Returns the price of a given token * @param rateProvider The rate provider associated with the token * @param minCandidate The token to calculate the minimum price for * @return The price of the given token */ function _calculateMinCandidatePrice(IRateProvider rateProvider, address minCandidate) internal returns (uint256) { uint256 minCandidatePrice = _getMarketPrice(minCandidate); if (address(rateProvider) != address(0)) { uint256 rateProviderPrice = rateProvider.getRate(); minCandidatePrice = minCandidatePrice.divDown(rateProviderPrice); } return minCandidatePrice; } /** * @notice Returns the price of a given token * @dev If the token is not supported by the base oracle, we assume that it is a nested pool * and we will try to get the price from the weighted pool oracle or recursively * @param token Address of the token to fetch the price for. * @return The Market price of the given token */ function _getMarketPrice(address token) internal returns (uint256) { try _base.getPrice(token) returns (uint256 price) { return price; } catch { try _weightedPoolOracle.getPrice(token) returns (uint256 price) { return price; } catch { return getPrice(token); } } } }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity ^0.8.0; import "./BalancerErrors.sol"; import "./LogExpMath.sol"; /* solhint-disable private-vars-leading-underscore */ /// forked from https://github.com/balancer-labs/balancer-v2-monorepo/blob/master/pkg/solidity-utils/contracts/math/FixedPoint.sol /// Updated to solidity version 0.8.X library FixedPoint { uint256 internal constant ONE = 1e18; // 18 decimal places uint256 internal constant TWO = 2 * ONE; uint256 internal constant FOUR = 4 * ONE; uint256 internal constant MAX_POW_RELATIVE_ERROR = 10000; // 10^(-14) // Minimum base for the power function when the exponent is 'free' (larger than ONE). uint256 internal constant MIN_POW_BASE_FREE_EXPONENT = 0.7e18; function add(uint256 a, uint256 b) internal pure returns (uint256) { // Fixed Point addition is the same as regular checked addition uint256 c = a + b; _require(c >= a, BalancerErrors.ADD_OVERFLOW); return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { // Fixed Point addition is the same as regular checked addition _require(b <= a, BalancerErrors.SUB_OVERFLOW); uint256 c = a - b; return c; } function mulDown(uint256 a, uint256 b) internal pure returns (uint256) { uint256 product = a * b; _require(a == 0 || product / a == b, BalancerErrors.MUL_OVERFLOW); return product / ONE; } function mulUp(uint256 a, uint256 b) internal pure returns (uint256) { uint256 product = a * b; _require(a == 0 || product / a == b, BalancerErrors.MUL_OVERFLOW); if (product == 0) { return 0; } else { // The traditional divUp formula is: // divUp(x, y) := (x + y - 1) / y // To avoid intermediate overflow in the addition, we distribute the division and get: // divUp(x, y) := (x - 1) / y + 1 // Note that this requires x != 0, which we already tested for. return ((product - 1) / ONE) + 1; } } function divDown(uint256 a, uint256 b) internal pure returns (uint256) { _require(b != 0, BalancerErrors.ZERO_DIVISION); if (a == 0) { return 0; } else { uint256 aInflated = a * ONE; _require(aInflated / a == ONE, BalancerErrors.DIV_INTERNAL); // mul overflow return aInflated / b; } } function divUp(uint256 a, uint256 b) internal pure returns (uint256) { _require(b != 0, BalancerErrors.ZERO_DIVISION); if (a == 0) { return 0; } else { uint256 aInflated = a * ONE; _require(aInflated / a == ONE, BalancerErrors.DIV_INTERNAL); // mul overflow // The traditional divUp formula is: // divUp(x, y) := (x + y - 1) / y // To avoid intermediate overflow in the addition, we distribute the division and get: // divUp(x, y) := (x - 1) / y + 1 // Note that this requires x != 0, which we already tested for. return ((aInflated - 1) / b) + 1; } } /** * @dev Returns x^y, assuming both are fixed point numbers, rounding down. The result is guaranteed to not be above * the true value (that is, the error function expected - actual is always positive). */ function powDown(uint256 x, uint256 y) internal pure returns (uint256) { // Optimize for when y equals 1.0, 2.0 or 4.0, as those are very simple to implement and occur often in 50/50 // and 80/20 Weighted Pools if (y == ONE) { return x; } else if (y == TWO) { return mulDown(x, x); } else if (y == FOUR) { uint256 square = mulDown(x, x); return mulDown(square, square); } else { uint256 raw = LogExpMath.pow(x, y); uint256 maxError = add(mulUp(raw, MAX_POW_RELATIVE_ERROR), 1); if (raw < maxError) { return 0; } else { return sub(raw, maxError); } } } /** * @dev Returns x^y, assuming both are fixed point numbers, rounding up. The result is guaranteed to not be below * the true value (that is, the error function expected - actual is always negative). */ function powUp(uint256 x, uint256 y) internal pure returns (uint256) { // Optimize for when y equals 1.0, 2.0 or 4.0, as those are very simple to implement and occur often in 50/50 // and 80/20 Weighted Pools if (y == ONE) { return x; } else if (y == TWO) { return mulUp(x, x); } else if (y == FOUR) { uint256 square = mulUp(x, x); return mulUp(square, square); } else { uint256 raw = LogExpMath.pow(x, y); uint256 maxError = add(mulUp(raw, MAX_POW_RELATIVE_ERROR), 1); return add(raw, maxError); } } /** * @dev Returns the complement of a value (1 - x), capped to 0 if x is larger than 1. * * Useful when computing the complement for values with some level of relative error, as it strips this error and * prevents intermediate negative values. */ function complement(uint256 x) internal pure returns (uint256) { return (x < ONE) ? (ONE - x) : 0; } }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // From https://github.com/balancer/balancer-v2-monorepo/blob/fc3e5735a07438ab506931f56adf64dede1441b1/pkg/pool-utils/contracts/lib/VaultReentrancyLib.sol pragma solidity >=0.7.1 <0.9.0; import "./BalancerErrors.sol"; import "../../interfaces/balancer-v2/IBalancerVault.sol"; library VaultReentrancyLib { /** * @dev Ensure we are not in a Vault context when this function is called, by attempting a no-op internal * balance operation. If we are already in a Vault transaction (e.g., a swap, join, or exit), the Vault's * reentrancy protection will cause this function to revert. * * The exact function call doesn't really matter: we're just trying to trigger the Vault reentrancy check * (and not hurt anything in case it works). An empty operation array with no specific operation at all works * for that purpose, and is also the least expensive in terms of gas and bytecode size. * * Call this at the top of any function that can cause a state change in a pool and is either public itself, * or called by a public function *outside* a Vault operation (e.g., join, exit, or swap). * * If this is *not* called in functions that are vulnerable to the read-only reentrancy issue described * here (https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345), those functions are unsafe, * and subject to manipulation that may result in loss of funds. */ function ensureNotInVaultContext(IBalancerVault vault) internal view { // Perform the following operation to trigger the Vault's reentrancy guard: // // IVault.UserBalanceOp[] memory noop = new IVault.UserBalanceOp[](0); // _vault.manageUserBalance(noop); // // However, use a static call so that it can be a view function (even though the function is non-view). // This allows the library to be used more widely, as some functions that need to be protected might be // view. // // This staticcall always reverts, but we need to make sure it doesn't fail due to a re-entrancy attack. // Staticcalls consume all gas forwarded to them on a revert caused by storage modification. // By default, almost the entire available gas is forwarded to the staticcall, // causing the entire call to revert with an 'out of gas' error. // // We set the gas limit to 10k for the staticcall to // avoid wasting gas when it reverts due to storage modification. // `manageUserBalance` is a non-reentrant function in the Vault, so calling it invokes `_enterNonReentrant` // in the `ReentrancyGuard` contract, reproduced here: // // function _enterNonReentrant() private { // // If the Vault is actually being reentered, it will revert in the first line, at the `_require` that // // checks the reentrancy flag, with "BAL#400" (corresponding to BalancerErrors.REENTRANCY) in the revertData. // // The full revertData will be: `abi.encodeWithSignature("Error(string)", "BAL#400")`. // _require(_status != _ENTERED, BalancerErrors.REENTRANCY); // // // If the Vault is not being reentered, the check above will pass: but it will *still* revert, // // because the next line attempts to modify storage during a staticcall. However, this type of // // failure results in empty revertData. // _status = _ENTERED; // } // // So based on this analysis, there are only two possible revertData values: empty, or abi.encoded BAL#400. // // It is of course much more bytecode and gas efficient to check for zero-length revertData than to compare it // to the encoded REENTRANCY revertData. // // While it should be impossible for the call to fail in any other way (especially since it reverts before // `manageUserBalance` even gets called), any other error would generate non-zero revertData, so checking for // empty data guards against this case too. (, bytes memory revertData) = address(vault).staticcall{ gas: 10_000 }( abi.encodeWithSelector(vault.manageUserBalance.selector, 0) ); _require(revertData.length == 0, BalancerErrors.REENTRANCY); } }
// SPDX-License-Identifier: MIT /* ██████╗ ██╗ ██╗ ██╗███████╗██████╗ ███████╗██████╗ ██████╗ ██╗ ██╗ ██╔══██╗██║ ██║ ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝ ██████╔╝██║ ██║ ██║█████╗ ██████╔╝█████╗ ██████╔╝██████╔╝ ╚████╔╝ ██╔══██╗██║ ██║ ██║██╔══╝ ██╔══██╗██╔══╝ ██╔══██╗██╔══██╗ ╚██╔╝ ██████╔╝███████╗╚██████╔╝███████╗██████╔╝███████╗██║ ██║██║ ██║ ██║ ╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ */ /** * @title BlueberryErrors * @author BlueberryProtocol * @notice containing all errors used in Blueberry protocol */ /// title BlueberryErrors /// @notice containing all errors used in Blueberry protocol pragma solidity 0.8.22; /*////////////////////////////////////////////////////////////////////////// COMMON ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when an action involves zero amount of tokens. error ZERO_AMOUNT(); /// @notice Thrown when the address provided is the zero address. error ZERO_ADDRESS(); /// @notice Thrown when the lengths of input arrays do not match. error INPUT_ARRAY_MISMATCH(); /// @notice Thrown when the caller is not authorized to call the function. error UNAUTHORIZED(); /*////////////////////////////////////////////////////////////////////////// ORACLE ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when the delay time exceeds allowed limits. error TOO_LONG_DELAY(uint256 delayTime); /// @notice Thrown when there's no maximum delay set for a token. error NO_MAX_DELAY(address token); /// @notice Thrown when the price information for a token is outdated. error PRICE_OUTDATED(address token); /// @notice Thrown when the price obtained is negative. error PRICE_NEGATIVE(address token); /// @notice Thrown when the sequencer is offline error SEQUENCER_DOWN(address sequencer); /// @notice Thrown when the grace period for a sequencer is not over yet. error SEQUENCER_GRACE_PERIOD_NOT_OVER(address sequencer); /// @notice Thrown when the price deviation exceeds allowed limits. error OUT_OF_DEVIATION_CAP(uint256 deviation); /// @notice Thrown when the number of sources exceeds the allowed length. error EXCEED_SOURCE_LEN(uint256 length); /// @notice Thrown when no primary source is available for the token. error NO_PRIMARY_SOURCE(address token); /// @notice Thrown when no valid price source is available for the token. error NO_VALID_SOURCE(address token); /// @notice Thrown when the deviation value exceeds the threshold. error EXCEED_DEVIATION(); /// @notice Thrown when the mean price is below the acceptable threshold. error TOO_LOW_MEAN(uint256 mean); /// @notice Thrown when no mean price is set for the token. error NO_MEAN(address token); /// @notice Thrown when no stable pool exists for the token. error NO_STABLEPOOL(address token); /// @notice Thrown when the price fetch process fails for a token. error PRICE_FAILED(address token); /// @notice Thrown when the liquidation threshold is set too high. error LIQ_THRESHOLD_TOO_HIGH(uint256 threshold); /// @notice Thrown when the liquidation threshold is set too low. error LIQ_THRESHOLD_TOO_LOW(uint256 threshold); /// @notice Thrown when the oracle doesn't support a specific token. error ORACLE_NOT_SUPPORT(address token); /// @notice Thrown when the oracle doesn't support a specific LP pair token. error ORACLE_NOT_SUPPORT_LP(address lp); /// @notice Thrown when the oracle doesn't support a specific wToken. error ORACLE_NOT_SUPPORT_WTOKEN(address wToken); /// @notice Thrown when there is no route to fetch data for the oracle error NO_ORACLE_ROUTE(address token); /// @notice Thrown when a value is out of an acceptable range. error VALUE_OUT_OF_RANGE(); /// @notice Thrown when specified limits are incorrect. error INCORRECT_LIMITS(); /// @notice Thrown when Curve LP is already registered. error CRV_LP_ALREADY_REGISTERED(address lp); /*////////////////////////////////////////////////////////////////////////// GENERAL SPELL ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when the caller isn't recognized as a bank. error NOT_BANK(address caller); /// @notice Thrown when the collateral doesn't exist for a strategy. error COLLATERAL_NOT_EXIST(uint256 strategyId, address colToken); /// @notice Thrown when the strategy ID doesn't correspond to an existing strategy. error STRATEGY_NOT_EXIST(address spell, uint256 strategyId); /// @notice Thrown when the position size exceeds maximum limits. error EXCEED_MAX_POS_SIZE(uint256 strategyId); /// @notice Thrown when the position size is below minimum requirements. error EXCEED_MIN_POS_SIZE(uint256 strategyId); /// @notice Thrown when the loan-to-value ratio exceeds allowed maximum. error EXCEED_MAX_LTV(); /// @notice Thrown when the strategy ID provided is incorrect. error INCORRECT_STRATEGY_ID(uint256 strategyId); /// @notice Thrown when the position size is invalid. error INVALID_POS_SIZE(); /// @notice Thrown when an incorrect liquidity pool token is provided. error INCORRECT_LP(address lpToken); /// @notice Thrown when an incorrect pool ID is provided. error INCORRECT_PID(uint256 pid); /// @notice Thrown when an incorrect collateral token is provided. error INCORRECT_COLTOKEN(address colToken); /// @notice Thrown when an incorrect underlying token is provided. error INCORRECT_UNDERLYING(address uToken); /// @notice Thrown when an incorrect debt token is provided. error INCORRECT_DEBT(address debtToken); /// @notice Thrown when a swap fails. error SWAP_FAILED(address swapToken); /*////////////////////////////////////////////////////////////////////////// VAULT ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when borrowing from the vault fails. error BORROW_FAILED(uint256 amount); /// @notice Thrown when repaying to the vault fails. error REPAY_FAILED(uint256 amount); /// @notice Thrown when lending to the vault fails. error LEND_FAILED(uint256 amount); /// @notice Thrown when redeeming from the vault fails. error REDEEM_FAILED(uint256 amount); /*////////////////////////////////////////////////////////////////////////// WRAPPER ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when a duplicate tokenId is added. error DUPLICATE_TOKEN_ID(uint256 tokenId); /// @notice Thrown when an invalid token ID is provided. error INVALID_TOKEN_ID(uint256 tokenId); /// @notice Thrown when an incorrect pool ID is provided. error BAD_PID(uint256 pid); /// @notice Thrown when a mismatch in reward per share is detected. error BAD_REWARD_PER_SHARE(uint256 rewardPerShare); /*////////////////////////////////////////////////////////////////////////// BANK ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when a function is called without a required execution flag. error NOT_UNDER_EXECUTION(); /// @notice Thrown when a transaction isn't initiated by the expected spell. error NOT_FROM_SPELL(address from); /// @notice Thrown when the sender is not the owner of a given position ID. error NOT_FROM_OWNER(uint256 positionId, address sender); /// @notice Thrown when a spell address isn't whitelisted. error SPELL_NOT_WHITELISTED(address spell); /// @notice Thrown when a token isn't whitelisted. error TOKEN_NOT_WHITELISTED(address token); /// @notice Thrown when a bank isn't listed for a given token. error BANK_NOT_LISTED(address token); /// @notice Thrown when a bank doesn't exist for an index. error BANK_NOT_EXIST(uint8 index); /// @notice Thrown when a bank is already listed for a given token. error BANK_ALREADY_LISTED(); /// @notice Thrown when the bank limit is reached. error BANK_LIMIT(); /// @notice Thrown when the BTOKEN is already added. error BTOKEN_ALREADY_ADDED(); /// @notice Thrown when the lending action isn't allowed. error LEND_NOT_ALLOWED(); /// @notice Thrown when the borrowing action isn't allowed. error BORROW_NOT_ALLOWED(); /// @notice Thrown when the repaying action isn't allowed. error REPAY_NOT_ALLOWED(); /// @notice Thrown when the redeeming action isn't allowed. error WITHDRAW_LEND_NOT_ALLOWED(); /// @notice Thrown when certain actions are locked. error LOCKED(); /// @notice Thrown when an action isn't executed. error NOT_IN_EXEC(); /// @notice Thrown when the repayment allowance hasn't been warmed up. error REPAY_ALLOW_NOT_WARMED_UP(); /// @notice Thrown when a different collateral type exists. error DIFF_COL_EXIST(address collToken); /// @notice Thrown when a position is not eligible for liquidation. error NOT_LIQUIDATABLE(uint256 positionId); /// @notice Thrown when a position is flagged as bad or invalid. error BAD_POSITION(uint256 posId); /// @notice Thrown when collateral for a specific position is flagged as bad or invalid. error BAD_COLLATERAL(uint256 positionId); /// @notice Thrown when there's insufficient collateral for an operation. error INSUFFICIENT_COLLATERAL(); /// @notice Thrown when an attempted repayment exceeds the actual debt. error REPAY_EXCEEDS_DEBT(uint256 repay, uint256 debt); /// @notice Thrown when an invalid utility token is provided. error INVALID_UTOKEN(address uToken); /// @notice Thrown when a borrow operation results in zero shares. error BORROW_ZERO_SHARE(uint256 borrowAmount); /*////////////////////////////////////////////////////////////////////////// CONFIGURATION ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when a certain ratio is too high for an operation. error RATIO_TOO_HIGH(uint256 ratio); /// @notice Thrown when an invalid fee distribution is detected. error INVALID_FEE_DISTRIBUTION(); /// @notice Thrown when no treasury is set for fee distribution. error NO_TREASURY_SET(); /// @notice Thrown when a fee window has already started. error FEE_WINDOW_ALREADY_STARTED(); /// @notice Thrown when a fee window duration is too long. error FEE_WINDOW_TOO_LONG(uint256 windowTime); /*////////////////////////////////////////////////////////////////////////// UTILITY ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when an operation has surpassed its deadline. error EXPIRED(uint256 deadline);
// SPDX-License-Identifier: MIT /* ██████╗ ██╗ ██╗ ██╗███████╗██████╗ ███████╗██████╗ ██████╗ ██╗ ██╗ ██╔══██╗██║ ██║ ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝ ██████╔╝██║ ██║ ██║█████╗ ██████╔╝█████╗ ██████╔╝██████╔╝ ╚████╔╝ ██╔══██╗██║ ██║ ██║██╔══╝ ██╔══██╗██╔══╝ ██╔══██╗██╔══██╗ ╚██╔╝ ██████╔╝███████╗╚██████╔╝███████╗██████╔╝███████╗██║ ██║██║ ██║ ██║ ╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ */ pragma solidity 0.8.22; import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import { IBaseOracle } from "../interfaces/IBaseOracle.sol"; /** * @title UsingBaseOracle * @author BlueberryProtocol * @dev This contract serves as a base for other contracts that need access * to an external oracle service. It provides an immutable reference to a * specified oracle source. */ abstract contract UsingBaseOracle is Ownable2StepUpgradeable { /// @dev Base oracle source IBaseOracle internal _base; /*////////////////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////////////////*/ /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /*////////////////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /* solhint-disable func-name-mixedcase */ /** * @dev Initializes the Base oracle source. * @param base Address of the Base oracle source. * @param owner Address of the owner. */ function __UsingBaseOracle_init(IBaseOracle base, address owner) internal onlyInitializing { _base = base; __Ownable2Step_init(); _transferOwnership(owner); } /* solhint-enable func-name-mixedcase */ /// @notice Returns the address of the Base oracle source. function getBaseOracle() public view returns (IBaseOracle) { return _base; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[10] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; /** * @title IBaseOracle * @author BlueberryProtocol * @notice Interface for a basic oracle that provides price data for assets. */ interface IBaseOracle { /** * @notice Event emitted when a new LP token is registered within its respective implementation. * @param token Address of the LP token being registered */ event RegisterLpToken(address token); /** * @notice Fetches the price of the given token in USD with 18 decimals precision. * @param token Address of the ERC-20 token for which the price is requested. * @return The USD price of the given token, multiplied by 10**18. */ function getPrice(address token) external returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; import { IBalancerV2Pool } from "./IBalancerV2Pool.sol"; interface IBalancerV2StablePool is IBalancerV2Pool { function getRate() external view returns (uint256); function getBptIndex() external view returns (uint256); function getRateProviders() external view returns (address[] memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; import { IAsset } from "./IAsset.sol"; interface IBalancerVault { enum UserBalanceOpKind { DEPOSIT_INTERNAL, WITHDRAW_INTERNAL, TRANSFER_INTERNAL, TRANSFER_EXTERNAL } /** * @dev Data for `manageUserBalance` operations, which include the possibility for ETH to be sent and received without manual WETH wrapping or unwrapping. */ struct UserBalanceOp { UserBalanceOpKind kind; IAsset asset; uint256 amount; address sender; address payable recipient; } struct JoinPoolRequest { address[] assets; uint256[] maxAmountsIn; bytes userData; bool fromInternalBalance; } struct ExitPoolRequest { address[] assets; uint256[] minAmountsOut; bytes userData; bool toInternalBalance; } function joinPool( bytes32 poolId, address sender, address recipient, JoinPoolRequest memory request ) external payable; function exitPool(bytes32 poolId, address sender, address recipient, ExitPoolRequest memory request) external; function getPoolTokens( bytes32 poolId ) external view returns (address[] memory tokens, uint256[] memory balances, uint256 lastChangedBlock); function getPool(bytes32 pid) external view returns (address pool, uint256 poolType); function manageUserBalance(UserBalanceOp[] memory ops) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; interface IRateProvider { function getRate() external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity ^0.8.0; /// Forked from https://github.com/balancer-labs/balancer-v2-monorepo/blob/3703c43c89dc693b918d20ebb0d9e4b205d31c2c/contracts/lib/helpers/BalancerErrors.sol /// Updated solidity version to 0.8.X // solhint-disable /** * @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are * supported. * Uses the default 'BAL' prefix for the error code */ function _require(bool condition, uint256 errorCode) pure { if (!condition) _revert(errorCode); } /** * @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are * supported. */ function _require(bool condition, uint256 errorCode, bytes3 prefix) pure { if (!condition) _revert(errorCode, prefix); } /** * @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported. * Uses the default 'BAL' prefix for the error code */ function _revert(uint256 errorCode) pure { _revert(errorCode, 0x42414c); // This is the raw byte representation of "BAL" } /** * @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported. */ function _revert(uint256 errorCode, bytes3 prefix) pure { uint256 prefixUint = uint256(uint24(prefix)); // We're going to dynamically create a revert string based on the error code, with the following format: // 'BAL#{errorCode}' // where the code is left-padded with zeroes to three digits (so they range from 000 to 999). // // We don't have revert strings embedded in the contract to save bytecode size: it takes much less space to store a // number (8 to 16 bits) than the individual string characters. // // The dynamic string creation algorithm that follows could be implemented in Solidity, but assembly allows for a // much denser implementation, again saving bytecode size. Given this function unconditionally reverts, this is a // safe place to rely on it without worrying about how its usage might affect e.g. memory contents. assembly { // First, we need to compute the ASCII representation of the error code. We assume that it is in the 0-999 // range, so we only need to convert three digits. To convert the digits to ASCII, we add 0x30, the value for // the '0' character. let units := add(mod(errorCode, 10), 0x30) errorCode := div(errorCode, 10) let tenths := add(mod(errorCode, 10), 0x30) errorCode := div(errorCode, 10) let hundreds := add(mod(errorCode, 10), 0x30) // With the individual characters, we can now construct the full string. // We first append the '#' character (0x23) to the prefix. In the case of 'BAL', it results in 0x42414c23 ('BAL#') // Then, we shift this by 24 (to provide space for the 3 bytes of the error code), and add the // characters to it, each shifted by a multiple of 8. // The revert reason is then shifted left by 200 bits (256 minus the length of the string, 7 characters * 8 bits // per character = 56) to locate it in the most significant part of the 256 slot (the beginning of a byte // array). let formattedPrefix := shl(24, add(0x23, shl(8, prefixUint))) let revertReason := shl(200, add(formattedPrefix, add(add(units, shl(8, tenths)), shl(16, hundreds)))) // We can now encode the reason in memory, which can be safely overwritten as we're about to revert. The encoded // message will have the following layout: // [ revert reason identifier ] [ string location offset ] [ string length ] [ string contents ] // The Solidity revert reason identifier is 0x08c739a0, the function selector of the Error(string) function. We // also write zeroes to the next 28 bytes of memory, but those are about to be overwritten. mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000) // Next is the offset to the location of the string, which will be placed immediately after (20 bytes away). mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) // The string length is fixed: 7 characters. mstore(0x24, 7) // Finally, the string itself is stored. mstore(0x44, revertReason) // Even if the string is only 7 bytes long, we need to return a full 32 byte slot containing it. The length of // the encoded message is therefore 4 + 32 + 32 + 32 = 100. revert(0, 100) } } library BalancerErrors { // Math uint256 internal constant ADD_OVERFLOW = 0; uint256 internal constant SUB_OVERFLOW = 1; uint256 internal constant SUB_UNDERFLOW = 2; uint256 internal constant MUL_OVERFLOW = 3; uint256 internal constant ZERO_DIVISION = 4; uint256 internal constant DIV_INTERNAL = 5; uint256 internal constant X_OUT_OF_BOUNDS = 6; uint256 internal constant Y_OUT_OF_BOUNDS = 7; uint256 internal constant PRODUCT_OUT_OF_BOUNDS = 8; uint256 internal constant INVALID_EXPONENT = 9; // Input uint256 internal constant OUT_OF_BOUNDS = 100; uint256 internal constant UNSORTED_ARRAY = 101; uint256 internal constant UNSORTED_TOKENS = 102; uint256 internal constant INPUT_LENGTH_MISMATCH = 103; uint256 internal constant ZERO_TOKEN = 104; // Shared pools uint256 internal constant MIN_TOKENS = 200; uint256 internal constant MAX_TOKENS = 201; uint256 internal constant MAX_SWAP_FEE_PERCENTAGE = 202; uint256 internal constant MIN_SWAP_FEE_PERCENTAGE = 203; uint256 internal constant MINIMUM_BPT = 204; uint256 internal constant CALLER_NOT_VAULT = 205; uint256 internal constant UNINITIALIZED = 206; uint256 internal constant BPT_IN_MAX_AMOUNT = 207; uint256 internal constant BPT_OUT_MIN_AMOUNT = 208; uint256 internal constant EXPIRED_PERMIT = 209; uint256 internal constant NOT_TWO_TOKENS = 210; uint256 internal constant DISABLED = 211; // Pools uint256 internal constant MIN_AMP = 300; uint256 internal constant MAX_AMP = 301; uint256 internal constant MIN_WEIGHT = 302; uint256 internal constant MAX_STABLE_TOKENS = 303; uint256 internal constant MAX_IN_RATIO = 304; uint256 internal constant MAX_OUT_RATIO = 305; uint256 internal constant MIN_BPT_IN_FOR_TOKEN_OUT = 306; uint256 internal constant MAX_OUT_BPT_FOR_TOKEN_IN = 307; uint256 internal constant NORMALIZED_WEIGHT_INVARIANT = 308; uint256 internal constant INVALID_TOKEN = 309; uint256 internal constant UNHANDLED_JOIN_KIND = 310; uint256 internal constant ZERO_INVARIANT = 311; uint256 internal constant ORACLE_INVALID_SECONDS_QUERY = 312; uint256 internal constant ORACLE_NOT_INITIALIZED = 313; uint256 internal constant ORACLE_QUERY_TOO_OLD = 314; uint256 internal constant ORACLE_INVALID_INDEX = 315; uint256 internal constant ORACLE_BAD_SECS = 316; uint256 internal constant AMP_END_TIME_TOO_CLOSE = 317; uint256 internal constant AMP_ONGOING_UPDATE = 318; uint256 internal constant AMP_RATE_TOO_HIGH = 319; uint256 internal constant AMP_NO_ONGOING_UPDATE = 320; uint256 internal constant STABLE_INVARIANT_DIDNT_CONVERGE = 321; uint256 internal constant STABLE_GET_BALANCE_DIDNT_CONVERGE = 322; uint256 internal constant RELAYER_NOT_CONTRACT = 323; uint256 internal constant BASE_POOL_RELAYER_NOT_CALLED = 324; uint256 internal constant REBALANCING_RELAYER_REENTERED = 325; uint256 internal constant GRADUAL_UPDATE_TIME_TRAVEL = 326; uint256 internal constant SWAPS_DISABLED = 327; uint256 internal constant CALLER_IS_NOT_LBP_OWNER = 328; uint256 internal constant PRICE_RATE_OVERFLOW = 329; uint256 internal constant INVALID_JOIN_EXIT_KIND_WHILE_SWAPS_DISABLED = 330; uint256 internal constant WEIGHT_CHANGE_TOO_FAST = 331; uint256 internal constant LOWER_GREATER_THAN_UPPER_TARGET = 332; uint256 internal constant UPPER_TARGET_TOO_HIGH = 333; uint256 internal constant UNHANDLED_BY_LINEAR_POOL = 334; uint256 internal constant OUT_OF_TARGET_RANGE = 335; uint256 internal constant UNHANDLED_EXIT_KIND = 336; uint256 internal constant UNAUTHORIZED_EXIT = 337; uint256 internal constant MAX_MANAGEMENT_SWAP_FEE_PERCENTAGE = 338; uint256 internal constant UNHANDLED_BY_MANAGED_POOL = 339; uint256 internal constant UNHANDLED_BY_PHANTOM_POOL = 340; uint256 internal constant TOKEN_DOES_NOT_HAVE_RATE_PROVIDER = 341; uint256 internal constant INVALID_INITIALIZATION = 342; uint256 internal constant OUT_OF_NEW_TARGET_RANGE = 343; uint256 internal constant FEATURE_DISABLED = 344; uint256 internal constant UNINITIALIZED_POOL_CONTROLLER = 345; uint256 internal constant SET_SWAP_FEE_DURING_FEE_CHANGE = 346; uint256 internal constant SET_SWAP_FEE_PENDING_FEE_CHANGE = 347; uint256 internal constant CHANGE_TOKENS_DURING_WEIGHT_CHANGE = 348; uint256 internal constant CHANGE_TOKENS_PENDING_WEIGHT_CHANGE = 349; uint256 internal constant MAX_WEIGHT = 350; uint256 internal constant UNAUTHORIZED_JOIN = 351; uint256 internal constant MAX_MANAGEMENT_AUM_FEE_PERCENTAGE = 352; uint256 internal constant FRACTIONAL_TARGET = 353; // Lib uint256 internal constant REENTRANCY = 400; uint256 internal constant SENDER_NOT_ALLOWED = 401; uint256 internal constant PAUSED = 402; uint256 internal constant PAUSE_WINDOW_EXPIRED = 403; uint256 internal constant MAX_PAUSE_WINDOW_DURATION = 404; uint256 internal constant MAX_BUFFER_PERIOD_DURATION = 405; uint256 internal constant INSUFFICIENT_BALANCE = 406; uint256 internal constant INSUFFICIENT_ALLOWANCE = 407; uint256 internal constant ERC20_TRANSFER_FROM_ZERO_ADDRESS = 408; uint256 internal constant ERC20_TRANSFER_TO_ZERO_ADDRESS = 409; uint256 internal constant ERC20_MINT_TO_ZERO_ADDRESS = 410; uint256 internal constant ERC20_BURN_FROM_ZERO_ADDRESS = 411; uint256 internal constant ERC20_APPROVE_FROM_ZERO_ADDRESS = 412; uint256 internal constant ERC20_APPROVE_TO_ZERO_ADDRESS = 413; uint256 internal constant ERC20_TRANSFER_EXCEEDS_ALLOWANCE = 414; uint256 internal constant ERC20_DECREASED_ALLOWANCE_BELOW_ZERO = 415; uint256 internal constant ERC20_TRANSFER_EXCEEDS_BALANCE = 416; uint256 internal constant ERC20_BURN_EXCEEDS_ALLOWANCE = 417; uint256 internal constant SAFE_ERC20_CALL_FAILED = 418; uint256 internal constant ADDRESS_INSUFFICIENT_BALANCE = 419; uint256 internal constant ADDRESS_CANNOT_SEND_VALUE = 420; uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_INT256 = 421; uint256 internal constant GRANT_SENDER_NOT_ADMIN = 422; uint256 internal constant REVOKE_SENDER_NOT_ADMIN = 423; uint256 internal constant RENOUNCE_SENDER_NOT_ALLOWED = 424; uint256 internal constant BUFFER_PERIOD_EXPIRED = 425; uint256 internal constant CALLER_IS_NOT_OWNER = 426; uint256 internal constant NEW_OWNER_IS_ZERO = 427; uint256 internal constant CODE_DEPLOYMENT_FAILED = 428; uint256 internal constant CALL_TO_NON_CONTRACT = 429; uint256 internal constant LOW_LEVEL_CALL_FAILED = 430; uint256 internal constant NOT_PAUSED = 431; uint256 internal constant ADDRESS_ALREADY_ALLOWLISTED = 432; uint256 internal constant ADDRESS_NOT_ALLOWLISTED = 433; uint256 internal constant ERC20_BURN_EXCEEDS_BALANCE = 434; uint256 internal constant INVALID_OPERATION = 435; uint256 internal constant CODEC_OVERFLOW = 436; uint256 internal constant IN_RECOVERY_MODE = 437; uint256 internal constant NOT_IN_RECOVERY_MODE = 438; uint256 internal constant INDUCED_FAILURE = 439; uint256 internal constant EXPIRED_SIGNATURE = 440; uint256 internal constant MALFORMED_SIGNATURE = 441; uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_UINT64 = 442; uint256 internal constant UNHANDLED_FEE_TYPE = 443; // Vault uint256 internal constant INVALID_POOL_ID = 500; uint256 internal constant CALLER_NOT_POOL = 501; uint256 internal constant SENDER_NOT_ASSET_MANAGER = 502; uint256 internal constant USER_DOESNT_ALLOW_RELAYER = 503; uint256 internal constant INVALID_SIGNATURE = 504; uint256 internal constant EXIT_BELOW_MIN = 505; uint256 internal constant JOIN_ABOVE_MAX = 506; uint256 internal constant SWAP_LIMIT = 507; uint256 internal constant SWAP_DEADLINE = 508; uint256 internal constant CANNOT_SWAP_SAME_TOKEN = 509; uint256 internal constant UNKNOWN_AMOUNT_IN_FIRST_SWAP = 510; uint256 internal constant MALCONSTRUCTED_MULTIHOP_SWAP = 511; uint256 internal constant INTERNAL_BALANCE_OVERFLOW = 512; uint256 internal constant INSUFFICIENT_INTERNAL_BALANCE = 513; uint256 internal constant INVALID_ETH_INTERNAL_BALANCE = 514; uint256 internal constant INVALID_POST_LOAN_BALANCE = 515; uint256 internal constant INSUFFICIENT_ETH = 516; uint256 internal constant UNALLOCATED_ETH = 517; uint256 internal constant ETH_TRANSFER = 518; uint256 internal constant CANNOT_USE_ETH_SENTINEL = 519; uint256 internal constant TOKENS_MISMATCH = 520; uint256 internal constant TOKEN_NOT_REGISTERED = 521; uint256 internal constant TOKEN_ALREADY_REGISTERED = 522; uint256 internal constant TOKENS_ALREADY_SET = 523; uint256 internal constant TOKENS_LENGTH_MUST_BE_2 = 524; uint256 internal constant NONZERO_TOKEN_BALANCE = 525; uint256 internal constant BALANCE_TOTAL_OVERFLOW = 526; uint256 internal constant POOL_NO_TOKENS = 527; uint256 internal constant INSUFFICIENT_FLASH_LOAN_BALANCE = 528; // Fees uint256 internal constant SWAP_FEE_PERCENTAGE_TOO_HIGH = 600; uint256 internal constant FLASH_LOAN_FEE_PERCENTAGE_TOO_HIGH = 601; uint256 internal constant INSUFFICIENT_FLASH_LOAN_FEE_AMOUNT = 602; uint256 internal constant AUM_FEE_PERCENTAGE_TOO_HIGH = 603; // Misc uint256 internal constant UNIMPLEMENTED = 998; uint256 internal constant SHOULD_NOT_HAPPEN = 999; }
// SPDX-License-Identifier: MIT // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated // documentation files (the “Software”), to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the // Software. // THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pragma solidity ^0.8.0; import "./BalancerErrors.sol"; /* solhint-disable */ /// Forked from https://github.com/balancer-labs/balancer-v2-monorepo/blob/master/pkg/solidity-utils/contracts/math/LogExpMath.sol /// updated to solidity version 0.8.x /** * @dev Exponentiation and logarithm functions for 18 decimal fixed point numbers (both base and exponent/argument). * * Exponentiation and logarithm with arbitrary bases (x^y and log_x(y)) are implemented by conversion to natural * exponentiation and logarithm (where the base is Euler's number). * * @author Fernando Martinelli - @fernandomartinelli * @author Sergio Yuhjtman - @sergioyuhjtman * @author Daniel Fernandez - @dmf7z */ library LogExpMath { // All fixed point multiplications and divisions are inlined. This means we need to divide by ONE when multiplying // two numbers, and multiply by ONE when dividing them. // All arguments and return values are 18 decimal fixed point numbers. int256 constant ONE_18 = 1e18; // Internally, intermediate values are computed with higher precision as 20 decimal fixed point numbers, and in the // case of ln36, 36 decimals. int256 constant ONE_20 = 1e20; int256 constant ONE_36 = 1e36; // The domain of natural exponentiation is bound by the word size and number of decimals used. // // Because internally the result will be stored using 20 decimals, the largest possible result is // (2^255 - 1) / 10^20, which makes the largest exponent ln((2^255 - 1) / 10^20) = 130.700829182905140221. // The smallest possible result is 10^(-18), which makes largest negative argument // ln(10^(-18)) = -41.446531673892822312. // We use 130.0 and -41.0 to have some safety margin. int256 constant MAX_NATURAL_EXPONENT = 130e18; int256 constant MIN_NATURAL_EXPONENT = -41e18; // Bounds for ln_36's argument. Both ln(0.9) and ln(1.1) can be represented with 36 decimal places in a fixed point // 256 bit integer. int256 constant LN_36_LOWER_BOUND = ONE_18 - 1e17; int256 constant LN_36_UPPER_BOUND = ONE_18 + 1e17; uint256 constant MILD_EXPONENT_BOUND = 2**254 / uint256(ONE_20); // 18 decimal constants int256 constant x0 = 128000000000000000000; // 2ˆ7 int256 constant a0 = 38877084059945950922200000000000000000000000000000000000; // eˆ(x0) (no decimals) int256 constant x1 = 64000000000000000000; // 2ˆ6 int256 constant a1 = 6235149080811616882910000000; // eˆ(x1) (no decimals) // 20 decimal constants int256 constant x2 = 3200000000000000000000; // 2ˆ5 int256 constant a2 = 7896296018268069516100000000000000; // eˆ(x2) int256 constant x3 = 1600000000000000000000; // 2ˆ4 int256 constant a3 = 888611052050787263676000000; // eˆ(x3) int256 constant x4 = 800000000000000000000; // 2ˆ3 int256 constant a4 = 298095798704172827474000; // eˆ(x4) int256 constant x5 = 400000000000000000000; // 2ˆ2 int256 constant a5 = 5459815003314423907810; // eˆ(x5) int256 constant x6 = 200000000000000000000; // 2ˆ1 int256 constant a6 = 738905609893065022723; // eˆ(x6) int256 constant x7 = 100000000000000000000; // 2ˆ0 int256 constant a7 = 271828182845904523536; // eˆ(x7) int256 constant x8 = 50000000000000000000; // 2ˆ-1 int256 constant a8 = 164872127070012814685; // eˆ(x8) int256 constant x9 = 25000000000000000000; // 2ˆ-2 int256 constant a9 = 128402541668774148407; // eˆ(x9) int256 constant x10 = 12500000000000000000; // 2ˆ-3 int256 constant a10 = 113314845306682631683; // eˆ(x10) int256 constant x11 = 6250000000000000000; // 2ˆ-4 int256 constant a11 = 106449445891785942956; // eˆ(x11) /** * @dev Exponentiation (x^y) with unsigned 18 decimal fixed point base and exponent. * * Reverts if ln(x) * y is smaller than `MIN_NATURAL_EXPONENT`, or larger than `MAX_NATURAL_EXPONENT`. */ function pow(uint256 x, uint256 y) internal pure returns (uint256) { if (y == 0) { // We solve the 0^0 indetermination by making it equal one. return uint256(ONE_18); } if (x == 0) { return 0; } // Instead of computing x^y directly, we instead rely on the properties of logarithms and exponentiation to // arrive at that result. In particular, exp(ln(x)) = x, and ln(x^y) = y * ln(x). This means // x^y = exp(y * ln(x)). // The ln function takes a signed value, so we need to make sure x fits in the signed 256 bit range. _require(x >> 255 == 0, BalancerErrors.X_OUT_OF_BOUNDS); int256 x_int256 = int256(x); // We will compute y * ln(x) in a single step. Depending on the value of x, we can either use ln or ln_36. In // both cases, we leave the division by ONE_18 (due to fixed point multiplication) to the end. // This prevents y * ln(x) from overflowing, and at the same time guarantees y fits in the signed 256 bit range. _require(y < MILD_EXPONENT_BOUND, BalancerErrors.Y_OUT_OF_BOUNDS); int256 y_int256 = int256(y); int256 logx_times_y; if (LN_36_LOWER_BOUND < x_int256 && x_int256 < LN_36_UPPER_BOUND) { int256 ln_36_x = _ln_36(x_int256); // ln_36_x has 36 decimal places, so multiplying by y_int256 isn't as straightforward, since we can't just // bring y_int256 to 36 decimal places, as it might overflow. Instead, we perform two 18 decimal // multiplications and add the results: one with the first 18 decimals of ln_36_x, and one with the // (downscaled) last 18 decimals. logx_times_y = ((ln_36_x / ONE_18) * y_int256 + ((ln_36_x % ONE_18) * y_int256) / ONE_18); } else { logx_times_y = _ln(x_int256) * y_int256; } logx_times_y /= ONE_18; // Finally, we compute exp(y * ln(x)) to arrive at x^y _require( MIN_NATURAL_EXPONENT <= logx_times_y && logx_times_y <= MAX_NATURAL_EXPONENT, BalancerErrors.PRODUCT_OUT_OF_BOUNDS ); return uint256(exp(logx_times_y)); } /** * @dev Natural exponentiation (e^x) with signed 18 decimal fixed point exponent. * * Reverts if `x` is smaller than MIN_NATURAL_EXPONENT, or larger than `MAX_NATURAL_EXPONENT`. */ function exp(int256 x) internal pure returns (int256) { _require(x >= MIN_NATURAL_EXPONENT && x <= MAX_NATURAL_EXPONENT, BalancerErrors.INVALID_EXPONENT); if (x < 0) { // We only handle positive exponents: e^(-x) is computed as 1 / e^x. We can safely make x positive since it // fits in the signed 256 bit range (as it is larger than MIN_NATURAL_EXPONENT). // Fixed point division requires multiplying by ONE_18. return ((ONE_18 * ONE_18) / exp(-x)); } // First, we use the fact that e^(x+y) = e^x * e^y to decompose x into a sum of powers of two, which we call x_n, // where x_n == 2^(7 - n), and e^x_n = a_n has been precomputed. We choose the first x_n, x0, to equal 2^7 // because all larger powers are larger than MAX_NATURAL_EXPONENT, and therefore not present in the // decomposition. // At the end of this process we will have the product of all e^x_n = a_n that apply, and the remainder of this // decomposition, which will be lower than the smallest x_n. // exp(x) = k_0 * a_0 * k_1 * a_1 * ... + k_n * a_n * exp(remainder), where each k_n equals either 0 or 1. // We mutate x by subtracting x_n, making it the remainder of the decomposition. // The first two a_n (e^(2^7) and e^(2^6)) are too large if stored as 18 decimal numbers, and could cause // intermediate overflows. Instead we store them as plain integers, with 0 decimals. // Additionally, x0 + x1 is larger than MAX_NATURAL_EXPONENT, which means they will not both be present in the // decomposition. // For each x_n, we test if that term is present in the decomposition (if x is larger than it), and if so deduct // it and compute the accumulated product. int256 firstAN; if (x >= x0) { x -= x0; firstAN = a0; } else if (x >= x1) { x -= x1; firstAN = a1; } else { firstAN = 1; // One with no decimal places } // We now transform x into a 20 decimal fixed point number, to have enhanced precision when computing the // smaller terms. x *= 100; // `product` is the accumulated product of all a_n (except a0 and a1), which starts at 20 decimal fixed point // one. Recall that fixed point multiplication requires dividing by ONE_20. int256 product = ONE_20; if (x >= x2) { x -= x2; product = (product * a2) / ONE_20; } if (x >= x3) { x -= x3; product = (product * a3) / ONE_20; } if (x >= x4) { x -= x4; product = (product * a4) / ONE_20; } if (x >= x5) { x -= x5; product = (product * a5) / ONE_20; } if (x >= x6) { x -= x6; product = (product * a6) / ONE_20; } if (x >= x7) { x -= x7; product = (product * a7) / ONE_20; } if (x >= x8) { x -= x8; product = (product * a8) / ONE_20; } if (x >= x9) { x -= x9; product = (product * a9) / ONE_20; } // x10 and x11 are unnecessary here since we have high enough precision already. // Now we need to compute e^x, where x is small (in particular, it is smaller than x9). We use the Taylor series // expansion for e^x: 1 + x + (x^2 / 2!) + (x^3 / 3!) + ... + (x^n / n!). int256 seriesSum = ONE_20; // The initial one in the sum, with 20 decimal places. int256 term; // Each term in the sum, where the nth term is (x^n / n!). // The first term is simply x. term = x; seriesSum += term; // Each term (x^n / n!) equals the previous one times x, divided by n. Since x is a fixed point number, // multiplying by it requires dividing by ONE_20, but dividing by the non-fixed point n values does not. term = ((term * x) / ONE_20) / 2; seriesSum += term; term = ((term * x) / ONE_20) / 3; seriesSum += term; term = ((term * x) / ONE_20) / 4; seriesSum += term; term = ((term * x) / ONE_20) / 5; seriesSum += term; term = ((term * x) / ONE_20) / 6; seriesSum += term; term = ((term * x) / ONE_20) / 7; seriesSum += term; term = ((term * x) / ONE_20) / 8; seriesSum += term; term = ((term * x) / ONE_20) / 9; seriesSum += term; term = ((term * x) / ONE_20) / 10; seriesSum += term; term = ((term * x) / ONE_20) / 11; seriesSum += term; term = ((term * x) / ONE_20) / 12; seriesSum += term; // 12 Taylor terms are sufficient for 18 decimal precision. // We now have the first a_n (with no decimals), and the product of all other a_n present, and the Taylor // approximation of the exponentiation of the remainder (both with 20 decimals). All that remains is to multiply // all three (one 20 decimal fixed point multiplication, dividing by ONE_20, and one integer multiplication), // and then drop two digits to return an 18 decimal value. return (((product * seriesSum) / ONE_20) * firstAN) / 100; } /** * @dev Logarithm (log(arg, base), with signed 18 decimal fixed point base and argument. */ function log(int256 arg, int256 base) internal pure returns (int256) { // This performs a simple base change: log(arg, base) = ln(arg) / ln(base). // Both logBase and logArg are computed as 36 decimal fixed point numbers, either by using ln_36, or by // upscaling. int256 logBase; if (LN_36_LOWER_BOUND < base && base < LN_36_UPPER_BOUND) { logBase = _ln_36(base); } else { logBase = _ln(base) * ONE_18; } int256 logArg; if (LN_36_LOWER_BOUND < arg && arg < LN_36_UPPER_BOUND) { logArg = _ln_36(arg); } else { logArg = _ln(arg) * ONE_18; } // When dividing, we multiply by ONE_18 to arrive at a result with 18 decimal places return (logArg * ONE_18) / logBase; } /** * @dev Natural logarithm (ln(a)) with signed 18 decimal fixed point argument. */ function ln(int256 a) internal pure returns (int256) { // The real natural logarithm is not defined for negative numbers or zero. _require(a > 0, BalancerErrors.OUT_OF_BOUNDS); if (LN_36_LOWER_BOUND < a && a < LN_36_UPPER_BOUND) { return _ln_36(a) / ONE_18; } else { return _ln(a); } } /** * @dev Internal natural logarithm (ln(a)) with signed 18 decimal fixed point argument. */ function _ln(int256 a) private pure returns (int256) { if (a < ONE_18) { // Since ln(a^k) = k * ln(a), we can compute ln(a) as ln(a) = ln((1/a)^(-1)) = - ln((1/a)). If a is less // than one, 1/a will be greater than one, and this if statement will not be entered in the recursive call. // Fixed point division requires multiplying by ONE_18. return (-_ln((ONE_18 * ONE_18) / a)); } // First, we use the fact that ln^(a * b) = ln(a) + ln(b) to decompose ln(a) into a sum of powers of two, which // we call x_n, where x_n == 2^(7 - n), which are the natural logarithm of precomputed quantities a_n (that is, // ln(a_n) = x_n). We choose the first x_n, x0, to equal 2^7 because the exponential of all larger powers cannot // be represented as 18 fixed point decimal numbers in 256 bits, and are therefore larger than a. // At the end of this process we will have the sum of all x_n = ln(a_n) that apply, and the remainder of this // decomposition, which will be lower than the smallest a_n. // ln(a) = k_0 * x_0 + k_1 * x_1 + ... + k_n * x_n + ln(remainder), where each k_n equals either 0 or 1. // We mutate a by subtracting a_n, making it the remainder of the decomposition. // For reasons related to how `exp` works, the first two a_n (e^(2^7) and e^(2^6)) are not stored as fixed point // numbers with 18 decimals, but instead as plain integers with 0 decimals, so we need to multiply them by // ONE_18 to convert them to fixed point. // For each a_n, we test if that term is present in the decomposition (if a is larger than it), and if so divide // by it and compute the accumulated sum. int256 sum = 0; if (a >= a0 * ONE_18) { a /= a0; // Integer, not fixed point division sum += x0; } if (a >= a1 * ONE_18) { a /= a1; // Integer, not fixed point division sum += x1; } // All other a_n and x_n are stored as 20 digit fixed point numbers, so we convert the sum and a to this format. sum *= 100; a *= 100; // Because further a_n are 20 digit fixed point numbers, we multiply by ONE_20 when dividing by them. if (a >= a2) { a = (a * ONE_20) / a2; sum += x2; } if (a >= a3) { a = (a * ONE_20) / a3; sum += x3; } if (a >= a4) { a = (a * ONE_20) / a4; sum += x4; } if (a >= a5) { a = (a * ONE_20) / a5; sum += x5; } if (a >= a6) { a = (a * ONE_20) / a6; sum += x6; } if (a >= a7) { a = (a * ONE_20) / a7; sum += x7; } if (a >= a8) { a = (a * ONE_20) / a8; sum += x8; } if (a >= a9) { a = (a * ONE_20) / a9; sum += x9; } if (a >= a10) { a = (a * ONE_20) / a10; sum += x10; } if (a >= a11) { a = (a * ONE_20) / a11; sum += x11; } // a is now a small number (smaller than a_11, which roughly equals 1.06). This means we can use a Taylor series // that converges rapidly for values of `a` close to one - the same one used in ln_36. // Let z = (a - 1) / (a + 1). // ln(a) = 2 * (z + z^3 / 3 + z^5 / 5 + z^7 / 7 + ... + z^(2 * n + 1) / (2 * n + 1)) // Recall that 20 digit fixed point division requires multiplying by ONE_20, and multiplication requires // division by ONE_20. int256 z = ((a - ONE_20) * ONE_20) / (a + ONE_20); int256 z_squared = (z * z) / ONE_20; // num is the numerator of the series: the z^(2 * n + 1) term int256 num = z; // seriesSum holds the accumulated sum of each term in the series, starting with the initial z int256 seriesSum = num; // In each step, the numerator is multiplied by z^2 num = (num * z_squared) / ONE_20; seriesSum += num / 3; num = (num * z_squared) / ONE_20; seriesSum += num / 5; num = (num * z_squared) / ONE_20; seriesSum += num / 7; num = (num * z_squared) / ONE_20; seriesSum += num / 9; num = (num * z_squared) / ONE_20; seriesSum += num / 11; // 6 Taylor terms are sufficient for 36 decimal precision. // Finally, we multiply by 2 (non fixed point) to compute ln(remainder) seriesSum *= 2; // We now have the sum of all x_n present, and the Taylor approximation of the logarithm of the remainder (both // with 20 decimals). All that remains is to sum these two, and then drop two digits to return a 18 decimal // value. return (sum + seriesSum) / 100; } /** * @dev Intrnal high precision (36 decimal places) natural logarithm (ln(x)) with signed 18 decimal fixed point argument, * for x close to one. * * Should only be used if x is between LN_36_LOWER_BOUND and LN_36_UPPER_BOUND. */ function _ln_36(int256 x) private pure returns (int256) { // Since ln(1) = 0, a value of x close to one will yield a very small result, which makes using 36 digits // worthwhile. // First, we transform x to a 36 digit fixed point value. x *= ONE_18; // We will use the following Taylor expansion, which converges very rapidly. Let z = (x - 1) / (x + 1). // ln(x) = 2 * (z + z^3 / 3 + z^5 / 5 + z^7 / 7 + ... + z^(2 * n + 1) / (2 * n + 1)) // Recall that 36 digit fixed point division requires multiplying by ONE_36, and multiplication requires // division by ONE_36. int256 z = ((x - ONE_36) * ONE_36) / (x + ONE_36); int256 z_squared = (z * z) / ONE_36; // num is the numerator of the series: the z^(2 * n + 1) term int256 num = z; // seriesSum holds the accumulated sum of each term in the series, starting with the initial z int256 seriesSum = num; // In each step, the numerator is multiplied by z^2 num = (num * z_squared) / ONE_36; seriesSum += num / 3; num = (num * z_squared) / ONE_36; seriesSum += num / 5; num = (num * z_squared) / ONE_36; seriesSum += num / 7; num = (num * z_squared) / ONE_36; seriesSum += num / 9; num = (num * z_squared) / ONE_36; seriesSum += num / 11; num = (num * z_squared) / ONE_36; seriesSum += num / 13; num = (num * z_squared) / ONE_36; seriesSum += num / 15; // 8 Taylor terms are sufficient for 36 decimal precision. // All that remains is multiplying by 2 (non fixed point). return seriesSum * 2; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./OwnableUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides 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} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); function __Ownable2Step_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable2Step_init_unchained() internal onlyInitializing { } /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; interface IBalancerV2Pool { function getVault() external view returns (address); function getPoolId() external view returns (bytes32); function totalSupply() external view returns (uint256); function getActualSupply() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; interface IAsset { // solhint-disable-previous-line no-empty-blocks }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
{ "remappings": [ "@blueberry/=lib/blueberry-core/contracts/", "@blueberry-stakevest/=lib/blueberry-stakevest/src/", "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/", "src/=src/BlueberryContracts/", "openzeppelin-contracts-upgradeable/contracts/=lib/blueberry-stakevest/lib/openzeppelin-contracts-upgradeable/contracts/", "solady/=lib/blueberry-stakevest/lib/solady/", "@chainlink/=lib/blueberry-core/node_modules/@chainlink/", "@eth-optimism/=lib/blueberry-core/node_modules/@eth-optimism/contracts/", "@uniswap/=lib/blueberry-core/node_modules/@uniswap/", "base64-sol/=lib/blueberry-core/node_modules/base64-sol/", "blueberry-core/=lib/blueberry-core/contracts/", "blueberry-stakevest/=lib/blueberry-stakevest/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "eth-gas-reporter/=lib/blueberry-core/node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/", "hardhat-deploy/=lib/blueberry-core/node_modules/hardhat-deploy/", "hardhat/=lib/blueberry-core/node_modules/hardhat/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/", "openzeppelin/=lib/blueberry-stakevest/lib/openzeppelin-contracts-upgradeable/contracts/", "solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/", "v3-core/=lib/blueberry-stakevest/lib/v3-core/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"lp","type":"address"}],"name":"ORACLE_NOT_SUPPORT_LP","type":"error"},{"inputs":[],"name":"ZERO_ADDRESS","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","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":false,"internalType":"address","name":"token","type":"address"}],"name":"RegisterLpToken","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBaseOracle","outputs":[{"internalType":"contract IBaseOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bpt","type":"address"}],"name":"getBptInfo","outputs":[{"components":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address[]","name":"rateProviders","type":"address[]"}],"internalType":"struct StableBPTOracle.TokenInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getWeightedPoolOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IBalancerVault","name":"vault","type":"address"},{"internalType":"contract IBaseOracle","name":"base","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bpt","type":"address"}],"name":"registerBpt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"oracle","type":"address"}],"name":"setWeightedPoolOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50610019610026565b610021610026565b6100e5565b600054610100900460ff16156100925760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146100e3576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611461806100f46000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c806379ba50971161007157806379ba5097146101455780638da5cb5b1461014d57806396a421041461015e578063c0c53b8b1461017e578063e30c397814610191578063f2fde38b146101a257600080fd5b8063257cc90d146100b95780633088794e146100ce5780633158952b146100f857806341976e091461010b578063590ed5a71461012c578063715018a61461013d575b600080fd5b6100cc6100c736600461103c565b6101b5565b005b6097546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b6100cc61010636600461103c565b6105f6565b61011e61011936600461103c565b610647565b6040519081526020016100ef565b60a2546001600160a01b03166100db565b6100cc610733565b6100cc610747565b6033546001600160a01b03166100db565b61017161016c36600461103c565b6107c1565b6040516100ef919061109e565b6100cc61018c3660046110e0565b6108b4565b6065546001600160a01b03166100db565b6100cc6101b036600461103c565b6109e5565b6101bd610a56565b6001600160a01b0381166101e45760405163538ba4f960e01b815260040160405180910390fd5b60a3546040805163038fff2d60e41b8152905183926000926001600160a01b039182169263f94d4668928616916338fff2d09160048083019260209291908290030181865afa15801561023b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025f919061112b565b6040518263ffffffff1660e01b815260040161027d91815260200190565b600060405180830381865afa15801561029a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102c29190810190611227565b505090506000826001600160a01b031663238a2d596040518163ffffffff1660e01b8152600401600060405180830381865afa158015610306573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261032e91908101906112eb565b9050600082519050836001600160a01b03166382687a566040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610390575060408051601f3d908101601f1916820190925261038d9181019061112b565b60015b6103f65760408051808201825284815260208082018590526001600160a01b038816600090815260a482529290922081518051929391926103d49284920190610fad565b5060208281015180516103ed9260018501920190610fad565b509050506105b3565b6000610403600184611336565b67ffffffffffffffff81111561041b5761041b611144565b604051908082528060200260200182016040528015610444578160200160208202803683370190505b5090506000610454600185611336565b67ffffffffffffffff81111561046c5761046c611144565b604051908082528060200260200182016040528015610495578160200160208202803683370190505b5090506000805b8581101561055157848114610549578781815181106104bd576104bd611349565b60200260200101518483815181106104d7576104d7611349565b60200260200101906001600160a01b031690816001600160a01b03168152505086818151811061050957610509611349565b602002602001015183838151811061052357610523611349565b6001600160a01b0390921660209283029190910190910152816105458161135f565b9250505b60010161049c565b5060408051808201825284815260208082018590526001600160a01b038c16600090815260a482529290922081518051929391926105929284920190610fad565b5060208281015180516105ab9260018501920190610fad565b505050505050505b6040516001600160a01b03861681527f40b39da51b8530ffd459fd9b3a53974555c0744c0f8b0f15499c129933acbd909060200160405180910390a15050505050565b6105fe610a56565b6001600160a01b0381166106255760405163538ba4f960e01b815260040160405180910390fd5b60a280546001600160a01b0319166001600160a01b0392909216919091179055565b60a35460009061065f906001600160a01b0316610ab0565b600061066a836107c1565b80515190915060008190036106a25760405163385fd8c560e11b81526001600160a01b03851660048201526024015b60405180910390fd5b60006106b78360000151846020015184610b5d565b90506000856001600160a01b031663679aefce6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061071d919061112b565b90506107298282610be6565b9695505050505050565b61073b610a56565b6107456000610c30565b565b60655433906001600160a01b031681146107b55760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610699565b6107be81610c30565b50565b604080518082018252606080825260208083018290526001600160a01b038516600090815260a482528490208451815492830281018401865294850182815293949390928492849184018282801561084257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610824575b50505050508152602001600182018054806020026020016040519081016040528092919081815260200182805480156108a457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610886575b5050505050815250509050919050565b600054610100900460ff16158080156108d45750600054600160ff909116105b806108ee5750303b1580156108ee575060005460ff166001145b6109515760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610699565b6000805460ff191660011790558015610974576000805461ff0019166101001790555b61097e8383610c49565b60a380546001600160a01b0319166001600160a01b03861617905580156109df576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6109ed610a56565b606580546001600160a01b0383166001600160a01b03199091168117909155610a1e6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146107455760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610699565b604080516000602480830182905283518084039091018152604490920183526020820180516001600160e01b03166303a38fa160e21b17905291516001600160a01b0384169161271091610b049190611378565b6000604051808303818686fa925050503d8060008114610b40576040519150601f19603f3d011682016040523d82523d6000602084013e610b45565b606091505b50915050610b598151600014610190610c9c565b5050565b60008080805b84811015610bdb576000878281518110610b7f57610b7f611349565b602002602001015190506000878381518110610b9d57610b9d611349565b602002602001015190506000610bb38284610caa565b905085811080610bc1575083155b15610bcd578294508095505b505050806001019050610b63565b509095945050505050565b600080610bf383856113a7565b9050610c14841580610c0d575083610c0b86846113be565b145b6003610c9c565b610c26670de0b6b3a7640000826113be565b9150505b92915050565b606580546001600160a01b03191690556107be81610d42565b600054610100900460ff16610c705760405162461bcd60e51b8152600401610699906113e0565b609780546001600160a01b0319166001600160a01b038416179055610c93610d94565b610b5981610c30565b81610b5957610b5981610dc3565b600080610cb683610dd3565b90506001600160a01b03841615610d3b576000846001600160a01b031663679aefce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2b919061112b565b9050610d378282610eb5565b9150505b9392505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610dbb5760405162461bcd60e51b8152600401610699906113e0565b610745610f1a565b6107be816210905360ea1b610f4a565b6097546040516341976e0960e01b81526001600160a01b03838116600483015260009216906341976e09906024016020604051808303816000875af1925050508015610e3c575060408051601f3d908101601f19168201909252610e399181019061112b565b60015b610c2a5760a2546040516341976e0960e01b81526001600160a01b038481166004830152909116906341976e09906024016020604051808303816000875af1925050508015610ea8575060408051601f3d908101601f19168201909252610ea59181019061112b565b60015b610c2a57610c2a82610647565b6000610ec48215156004610c9c565b82600003610ed457506000610c2a565b6000610ee8670de0b6b3a7640000856113a7565b9050610f08670de0b6b3a7640000610f0086846113be565b146005610c9c565b610f1283826113be565b915050610c2a565b600054610100900460ff16610f415760405162461bcd60e51b8152600401610699906113e0565b61074533610c30565b62461bcd60e51b600090815260206004526007602452600a808404818106603090810160081b958390069590950190829004918206850160101b01602363ffffff0060e086901c160160181b0190930160c81b604481905260e883901c91606490fd5b828054828255906000526020600020908101928215611002579160200282015b8281111561100257825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190610fcd565b5061100e929150611012565b5090565b5b8082111561100e5760008155600101611013565b6001600160a01b03811681146107be57600080fd5b60006020828403121561104e57600080fd5b8135610d3b81611027565b60008151808452602080850194506020840160005b838110156110935781516001600160a01b03168752958201959082019060010161106e565b509495945050505050565b6020815260008251604060208401526110ba6060840182611059565b90506020840151601f198483030160408501526110d78282611059565b95945050505050565b6000806000606084860312156110f557600080fd5b833561110081611027565b9250602084013561111081611027565b9150604084013561112081611027565b809150509250925092565b60006020828403121561113d57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561118357611183611144565b604052919050565b600067ffffffffffffffff8211156111a5576111a5611144565b5060051b60200190565b600082601f8301126111c057600080fd5b815160206111d56111d08361118b565b61115a565b8083825260208201915060208460051b8701019350868411156111f757600080fd5b602086015b8481101561121c57805161120f81611027565b83529183019183016111fc565b509695505050505050565b60008060006060848603121561123c57600080fd5b835167ffffffffffffffff8082111561125457600080fd5b611260878388016111af565b945060209150818601518181111561127757600080fd5b86019050601f8101871361128a57600080fd5b80516112986111d08261118b565b81815260059190911b820183019083810190898311156112b757600080fd5b928401925b828410156112d5578351825292840192908401906112bc565b8096505050505050604084015190509250925092565b6000602082840312156112fd57600080fd5b815167ffffffffffffffff81111561131457600080fd5b610c26848285016111af565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c2a57610c2a611320565b634e487b7160e01b600052603260045260246000fd5b60006001820161137157611371611320565b5060010190565b6000825160005b81811015611399576020818601810151858301520161137f565b506000920191825250919050565b8082028115828204841417610c2a57610c2a611320565b6000826113db57634e487b7160e01b600052601260045260246000fd5b500490565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea2646970667358221220129abf25519126b9563c2706db767de067ebd1faabcb5e8d1dc46242de0f30b664736f6c63430008160033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100b45760003560e01c806379ba50971161007157806379ba5097146101455780638da5cb5b1461014d57806396a421041461015e578063c0c53b8b1461017e578063e30c397814610191578063f2fde38b146101a257600080fd5b8063257cc90d146100b95780633088794e146100ce5780633158952b146100f857806341976e091461010b578063590ed5a71461012c578063715018a61461013d575b600080fd5b6100cc6100c736600461103c565b6101b5565b005b6097546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b6100cc61010636600461103c565b6105f6565b61011e61011936600461103c565b610647565b6040519081526020016100ef565b60a2546001600160a01b03166100db565b6100cc610733565b6100cc610747565b6033546001600160a01b03166100db565b61017161016c36600461103c565b6107c1565b6040516100ef919061109e565b6100cc61018c3660046110e0565b6108b4565b6065546001600160a01b03166100db565b6100cc6101b036600461103c565b6109e5565b6101bd610a56565b6001600160a01b0381166101e45760405163538ba4f960e01b815260040160405180910390fd5b60a3546040805163038fff2d60e41b8152905183926000926001600160a01b039182169263f94d4668928616916338fff2d09160048083019260209291908290030181865afa15801561023b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025f919061112b565b6040518263ffffffff1660e01b815260040161027d91815260200190565b600060405180830381865afa15801561029a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102c29190810190611227565b505090506000826001600160a01b031663238a2d596040518163ffffffff1660e01b8152600401600060405180830381865afa158015610306573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261032e91908101906112eb565b9050600082519050836001600160a01b03166382687a566040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610390575060408051601f3d908101601f1916820190925261038d9181019061112b565b60015b6103f65760408051808201825284815260208082018590526001600160a01b038816600090815260a482529290922081518051929391926103d49284920190610fad565b5060208281015180516103ed9260018501920190610fad565b509050506105b3565b6000610403600184611336565b67ffffffffffffffff81111561041b5761041b611144565b604051908082528060200260200182016040528015610444578160200160208202803683370190505b5090506000610454600185611336565b67ffffffffffffffff81111561046c5761046c611144565b604051908082528060200260200182016040528015610495578160200160208202803683370190505b5090506000805b8581101561055157848114610549578781815181106104bd576104bd611349565b60200260200101518483815181106104d7576104d7611349565b60200260200101906001600160a01b031690816001600160a01b03168152505086818151811061050957610509611349565b602002602001015183838151811061052357610523611349565b6001600160a01b0390921660209283029190910190910152816105458161135f565b9250505b60010161049c565b5060408051808201825284815260208082018590526001600160a01b038c16600090815260a482529290922081518051929391926105929284920190610fad565b5060208281015180516105ab9260018501920190610fad565b505050505050505b6040516001600160a01b03861681527f40b39da51b8530ffd459fd9b3a53974555c0744c0f8b0f15499c129933acbd909060200160405180910390a15050505050565b6105fe610a56565b6001600160a01b0381166106255760405163538ba4f960e01b815260040160405180910390fd5b60a280546001600160a01b0319166001600160a01b0392909216919091179055565b60a35460009061065f906001600160a01b0316610ab0565b600061066a836107c1565b80515190915060008190036106a25760405163385fd8c560e11b81526001600160a01b03851660048201526024015b60405180910390fd5b60006106b78360000151846020015184610b5d565b90506000856001600160a01b031663679aefce6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061071d919061112b565b90506107298282610be6565b9695505050505050565b61073b610a56565b6107456000610c30565b565b60655433906001600160a01b031681146107b55760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610699565b6107be81610c30565b50565b604080518082018252606080825260208083018290526001600160a01b038516600090815260a482528490208451815492830281018401865294850182815293949390928492849184018282801561084257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610824575b50505050508152602001600182018054806020026020016040519081016040528092919081815260200182805480156108a457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610886575b5050505050815250509050919050565b600054610100900460ff16158080156108d45750600054600160ff909116105b806108ee5750303b1580156108ee575060005460ff166001145b6109515760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610699565b6000805460ff191660011790558015610974576000805461ff0019166101001790555b61097e8383610c49565b60a380546001600160a01b0319166001600160a01b03861617905580156109df576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6109ed610a56565b606580546001600160a01b0383166001600160a01b03199091168117909155610a1e6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146107455760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610699565b604080516000602480830182905283518084039091018152604490920183526020820180516001600160e01b03166303a38fa160e21b17905291516001600160a01b0384169161271091610b049190611378565b6000604051808303818686fa925050503d8060008114610b40576040519150601f19603f3d011682016040523d82523d6000602084013e610b45565b606091505b50915050610b598151600014610190610c9c565b5050565b60008080805b84811015610bdb576000878281518110610b7f57610b7f611349565b602002602001015190506000878381518110610b9d57610b9d611349565b602002602001015190506000610bb38284610caa565b905085811080610bc1575083155b15610bcd578294508095505b505050806001019050610b63565b509095945050505050565b600080610bf383856113a7565b9050610c14841580610c0d575083610c0b86846113be565b145b6003610c9c565b610c26670de0b6b3a7640000826113be565b9150505b92915050565b606580546001600160a01b03191690556107be81610d42565b600054610100900460ff16610c705760405162461bcd60e51b8152600401610699906113e0565b609780546001600160a01b0319166001600160a01b038416179055610c93610d94565b610b5981610c30565b81610b5957610b5981610dc3565b600080610cb683610dd3565b90506001600160a01b03841615610d3b576000846001600160a01b031663679aefce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2b919061112b565b9050610d378282610eb5565b9150505b9392505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610dbb5760405162461bcd60e51b8152600401610699906113e0565b610745610f1a565b6107be816210905360ea1b610f4a565b6097546040516341976e0960e01b81526001600160a01b03838116600483015260009216906341976e09906024016020604051808303816000875af1925050508015610e3c575060408051601f3d908101601f19168201909252610e399181019061112b565b60015b610c2a5760a2546040516341976e0960e01b81526001600160a01b038481166004830152909116906341976e09906024016020604051808303816000875af1925050508015610ea8575060408051601f3d908101601f19168201909252610ea59181019061112b565b60015b610c2a57610c2a82610647565b6000610ec48215156004610c9c565b82600003610ed457506000610c2a565b6000610ee8670de0b6b3a7640000856113a7565b9050610f08670de0b6b3a7640000610f0086846113be565b146005610c9c565b610f1283826113be565b915050610c2a565b600054610100900460ff16610f415760405162461bcd60e51b8152600401610699906113e0565b61074533610c30565b62461bcd60e51b600090815260206004526007602452600a808404818106603090810160081b958390069590950190829004918206850160101b01602363ffffff0060e086901c160160181b0190930160c81b604481905260e883901c91606490fd5b828054828255906000526020600020908101928215611002579160200282015b8281111561100257825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190610fcd565b5061100e929150611012565b5090565b5b8082111561100e5760008155600101611013565b6001600160a01b03811681146107be57600080fd5b60006020828403121561104e57600080fd5b8135610d3b81611027565b60008151808452602080850194506020840160005b838110156110935781516001600160a01b03168752958201959082019060010161106e565b509495945050505050565b6020815260008251604060208401526110ba6060840182611059565b90506020840151601f198483030160408501526110d78282611059565b95945050505050565b6000806000606084860312156110f557600080fd5b833561110081611027565b9250602084013561111081611027565b9150604084013561112081611027565b809150509250925092565b60006020828403121561113d57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561118357611183611144565b604052919050565b600067ffffffffffffffff8211156111a5576111a5611144565b5060051b60200190565b600082601f8301126111c057600080fd5b815160206111d56111d08361118b565b61115a565b8083825260208201915060208460051b8701019350868411156111f757600080fd5b602086015b8481101561121c57805161120f81611027565b83529183019183016111fc565b509695505050505050565b60008060006060848603121561123c57600080fd5b835167ffffffffffffffff8082111561125457600080fd5b611260878388016111af565b945060209150818601518181111561127757600080fd5b86019050601f8101871361128a57600080fd5b80516112986111d08261118b565b81815260059190911b820183019083810190898311156112b757600080fd5b928401925b828410156112d5578351825292840192908401906112bc565b8096505050505050604084015190509250925092565b6000602082840312156112fd57600080fd5b815167ffffffffffffffff81111561131457600080fd5b610c26848285016111af565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c2a57610c2a611320565b634e487b7160e01b600052603260045260246000fd5b60006001820161137157611371611320565b5060010190565b6000825160005b81811015611399576020818601810151858301520161137f565b506000920191825250919050565b8082028115828204841417610c2a57610c2a611320565b6000826113db57634e487b7160e01b600052601260045260246000fd5b500490565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fea2646970667358221220129abf25519126b9563c2706db767de067ebd1faabcb5e8d1dc46242de0f30b664736f6c63430008160033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.