Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
PriceFeedCurveLPTAssetSNG
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.20;
import {AggregatorV3Interface} from "src/interfaces/AggregatorV3Interface.sol";
import {BaseFeedCurveLPTAssetSNG} from "src/spectra-oracles/chainlinkFeeds/stableswap-ng/BaseFeedCurveLPTAsset.sol";
import {OwnableUpgradeable} from "openzeppelin-contracts-upgradeable/access/OwnableUpgradeable.sol";
/**
* @title PriceFeedCurveLPTAssetSNG
* @notice Curve PT price feed that gives the LPT price in a provided IBT/PT Curve Pool in asset
* @notice Designed to be used with stableswap-ng pools
*/
contract PriceFeedCurveLPTAssetSNG is BaseFeedCurveLPTAssetSNG, OwnableUpgradeable {
string public constant description = "IBT/PT Curve Pool Oracle: LPT price in asset";
constructor() {
_disableInitializers();
}
/**
* @notice Initializes the oracle
* @param _pt The principal token address
* @param _pool The pool address
*/
function initialize(address _pt, address _pool) external initializer {
__BaseFeedCurveLPTAssetSNG_init(_pt, _pool);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {ContextUpgradeable} from "../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.
*
* The initial owner is set to the address provided by the deployer. 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 {
/// @custom:storage-location erc7201:openzeppelin.storage.Ownable
struct OwnableStorage {
address _owner;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;
function _getOwnableStorage() private pure returns (OwnableStorage storage $) {
assembly {
$.slot := OwnableStorageLocation
}
}
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
function __Ownable_init(address initialOwner) internal onlyInitializing {
__Ownable_init_unchained(initialOwner);
}
function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @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) {
OwnableStorage storage $ = _getOwnableStorage();
return $._owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @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 {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
OwnableStorage storage $ = _getOwnableStorage();
address oldOwner = $._owner;
$._owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @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 Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._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 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._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() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @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 {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
assembly {
$.slot := INITIALIZABLE_STORAGE
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)
pragma solidity ^0.8.20;
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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC3156FlashBorrower.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC3156 FlashBorrower, as defined in
* https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].
*/
interface IERC3156FlashBorrower {
/**
* @dev Receive a flash loan.
* @param initiator The initiator of the loan.
* @param token The loan currency.
* @param amount The amount of tokens lent.
* @param fee The additional amount of tokens to repay.
* @param data Arbitrary data structure, intended to contain user-defined parameters.
* @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan"
*/
function onFlashLoan(
address initiator,
address token,
uint256 amount,
uint256 fee,
bytes calldata data
) external returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC3156FlashLender.sol)
pragma solidity ^0.8.20;
import {IERC3156FlashBorrower} from "./IERC3156FlashBorrower.sol";
/**
* @dev Interface of the ERC3156 FlashLender, as defined in
* https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].
*/
interface IERC3156FlashLender {
/**
* @dev The amount of currency available to be lended.
* @param token The loan currency.
* @return The amount of `token` that can be borrowed.
*/
function maxFlashLoan(address token) external view returns (uint256);
/**
* @dev The fee to be charged for a given loan.
* @param token The loan currency.
* @param amount The amount of tokens lent.
* @return The amount of `token` to be charged for the loan, on top of the returned principal.
*/
function flashFee(address token, uint256 amount) external view returns (uint256);
/**
* @dev Initiate a flash loan.
* @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
* @param token The loan currency.
* @param amount The amount of tokens lent.
* @param data Arbitrary data structure, intended to contain user-defined parameters.
*/
function flashLoan(
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC4626.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*/
interface IERC4626 is IERC20, IERC20Metadata {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// ? `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// ? `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/// @dev Interface of Chainlink v3 aggregator, as defined in
// https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol
// solhint-disable-next-line interface-starts-with-i
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
function getRoundData(
uint80 _roundId
)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;
import {IERC20Metadata} from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface for Curve TwoCrypto-NG pool
*/
interface ICurveNGPool is IERC20Metadata {
function coins(uint256 index) external view returns (address);
function balances(uint256 index) external view returns (uint256);
function A() external view returns (uint256);
function gamma() external view returns (uint256);
function D() external view returns (uint256);
function token() external view returns (address);
function price_scale() external view returns (uint256);
function price_oracle() external view returns (uint256);
function future_A_gamma_time() external view returns (uint256);
function future_A_gamma() external view returns (uint256);
function initial_A_gamma_time() external view returns (uint256);
function initial_A_gamma() external view returns (uint256);
function fee_gamma() external view returns (uint256);
function mid_fee() external view returns (uint256);
function out_fee() external view returns (uint256);
function allowed_extra_profit() external view returns (uint256);
function adjustment_step() external view returns (uint256);
function admin_fee() external view returns (uint256);
function ma_time() external view returns (uint256);
function get_virtual_price() external view returns (uint256);
function fee() external view returns (uint256);
function get_dy(uint256 i, uint256 j, uint256 dx) external view returns (uint256);
function get_dx(uint256 i, uint256 j, uint256 dy) external view returns (uint256);
function last_prices() external view returns (uint256);
function calc_token_amount(
uint256[2] calldata amounts,
bool deposit
) external view returns (uint256);
function calc_withdraw_one_coin(
uint256 _token_amount,
uint256 i
) external view returns (uint256);
function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external returns (uint256);
function exchange(
uint256 i,
uint256 j,
uint256 dx,
uint256 min_dy,
address receiver
) external returns (uint256);
function add_liquidity(
uint256[2] calldata amounts,
uint256 min_mint_amount
) external returns (uint256);
function add_liquidity(
uint256[2] calldata amounts,
uint256 min_mint_amount,
address receiver
) external returns (uint256);
function remove_liquidity(uint256 amount, uint256[2] calldata min_amounts) external;
function remove_liquidity(
uint256 amount,
uint256[2] calldata min_amounts,
address receiver
) external;
function remove_liquidity_one_coin(
uint256 token_amount,
uint256 i,
uint256 min_amount
) external;
function remove_liquidity_one_coin(
uint256 token_amount,
uint256 i,
uint256 min_amount,
address receiver
) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;
import "openzeppelin-contracts/interfaces/IERC20.sol";
import "openzeppelin-contracts/interfaces/IERC20Metadata.sol";
import "openzeppelin-contracts/interfaces/IERC3156FlashLender.sol";
interface IPrincipalToken is IERC20, IERC20Metadata, IERC3156FlashLender {
/* ERRORS
*****************************************************************************************************************/
error InvalidDecimals();
error BeaconNotSet();
error PTExpired();
error PTNotExpired();
error RateError();
error AddressError();
error UnauthorizedCaller();
error RatesAtExpiryAlreadyStored();
error ERC5143SlippageProtectionFailed();
error InsufficientBalance();
error FlashLoanExceedsMaxAmount();
error FlashLoanCallbackFailed();
error NoRewardsProxy();
error ClaimRewardsFailed();
/* Functions
*****************************************************************************************************************/
function initialize(address _ibt, uint256 _duration, address initialAuthority) external;
/**
* @notice Toggle Pause
* @dev Should only be called in extraordinary situations by the admin of the contract
*/
function pause() external;
/**
* @notice Toggle UnPause
* @dev Should only be called in extraordinary situations by the admin of the contract
*/
function unPause() external;
/**
* @notice Deposits amount of assets in the PT vault
* @param assets The amount of assets being deposited
* @param receiver The receiver address of the shares
* @return shares The amount of shares minted (same amount for PT & yt)
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @notice Deposits amount of assets in the PT vault
* @param assets The amount of assets being deposited
* @param ptReceiver The receiver address of the PTs
* @param ytReceiver the receiver address of the YTs
* @return shares The amount of shares minted (same amount for PT & yt)
*/
function deposit(
uint256 assets,
address ptReceiver,
address ytReceiver
) external returns (uint256 shares);
/**
* @notice Deposits amount of assets with a lower bound on shares received
* @param assets The amount of assets being deposited
* @param ptReceiver The receiver address of the PTs
* @param ytReceiver The receiver address of the YTs
* @param minShares The minimum allowed shares from this deposit
* @return shares The amount of shares actually minted to the receiver
*/
function deposit(
uint256 assets,
address ptReceiver,
address ytReceiver,
uint256 minShares
) external returns (uint256 shares);
/**
* @notice Same as normal deposit but with IBTs
* @param ibts The amount of IBT being deposited
* @param receiver The receiver address of the shares
* @return shares The amount of shares minted to the receiver
*/
function depositIBT(uint256 ibts, address receiver) external returns (uint256 shares);
/**
* @notice Same as normal deposit but with IBTs
* @param ibts The amount of IBT being deposited
* @param ptReceiver The receiver address of the PTs
* @param ytReceiver the receiver address of the YTs
* @return shares The amount of shares minted to the receiver
*/
function depositIBT(
uint256 ibts,
address ptReceiver,
address ytReceiver
) external returns (uint256 shares);
/**
* @notice Same as normal deposit but with IBTs
* @param ibts The amount of IBT being deposited
* @param ptReceiver The receiver address of the PTs
* @param ytReceiver The receiver address of the YTs
* @param minShares The minimum allowed shares from this deposit
* @return shares The amount of shares minted to the receiver
*/
function depositIBT(
uint256 ibts,
address ptReceiver,
address ytReceiver,
uint256 minShares
) external returns (uint256 shares);
/**
* @notice Burns owner's shares (PTs and YTs before expiry, PTs after expiry)
* and sends assets to receiver
* @param shares The amount of shares to burn
* @param receiver The address that will receive the assets
* @param owner The owner of the shares
* @return assets The actual amount of assets received for burning the shares
*/
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
/**
* @notice Burns owner's shares (PTs and YTs before expiry, PTs after expiry)
* and sends assets to receiver
* @param shares The amount of shares to burn
* @param receiver The address that will receive the assets
* @param owner The owner of the shares
* @param minAssets The minimum assets that should be returned to user
* @return assets The actual amount of assets received for burning the shares
*/
function redeem(
uint256 shares,
address receiver,
address owner,
uint256 minAssets
) external returns (uint256 assets);
/**
* @notice Burns owner's shares (PTs and YTs before expiry, PTs after expiry)
* and sends IBTs to receiver
* @param shares The amount of shares to burn
* @param receiver The address that will receive the IBTs
* @param owner The owner of the shares
* @return ibts The actual amount of IBT received for burning the shares
*/
function redeemForIBT(
uint256 shares,
address receiver,
address owner
) external returns (uint256 ibts);
/**
* @notice Burns owner's shares (PTs and YTs before expiry, PTs after expiry)
* and sends IBTs to receiver
* @param shares The amount of shares to burn
* @param receiver The address that will receive the IBTs
* @param owner The owner of the shares
* @param minIbts The minimum IBTs that should be returned to user
* @return ibts The actual amount of IBT received for burning the shares
*/
function redeemForIBT(
uint256 shares,
address receiver,
address owner,
uint256 minIbts
) external returns (uint256 ibts);
/**
* @notice Burns owner's shares (before expiry : PTs and YTs) and sends assets to receiver
* @param assets The amount of assets to be received
* @param receiver The address that will receive the assets
* @param owner The owner of the shares (PTs and YTs)
* @return shares The actual amount of shares burnt for receiving the assets
*/
function withdraw(
uint256 assets,
address receiver,
address owner
) external returns (uint256 shares);
/**
* @notice Burns owner's shares (before expiry : PTs and YTs) and sends assets to receiver
* @param assets The amount of assets to be received
* @param receiver The address that will receive the assets
* @param owner The owner of the shares (PTs and YTs)
* @param maxShares The maximum shares allowed to be burnt
* @return shares The actual amount of shares burnt for receiving the assets
*/
function withdraw(
uint256 assets,
address receiver,
address owner,
uint256 maxShares
) external returns (uint256 shares);
/**
* @notice Burns owner's shares (before expiry : PTs and YTs) and sends IBTs to receiver
* @param ibts The amount of IBT to be received
* @param receiver The address that will receive the IBTs
* @param owner The owner of the shares (PTs and YTs)
* @return shares The actual amount of shares burnt for receiving the IBTs
*/
function withdrawIBT(
uint256 ibts,
address receiver,
address owner
) external returns (uint256 shares);
/**
* @notice Burns owner's shares (before expiry : PTs and YTs) and sends IBTs to receiver
* @param ibts The amount of IBT to be received
* @param receiver The address that will receive the IBTs
* @param owner The owner of the shares (PTs and YTs)
* @param maxShares The maximum shares allowed to be burnt
* @return shares The actual amount of shares burnt for receiving the IBTs
*/
function withdrawIBT(
uint256 ibts,
address receiver,
address owner,
uint256 maxShares
) external returns (uint256 shares);
/**
* @notice Updates _user's yield since last update
* @param _user The user whose yield will be updated
* @return updatedUserYieldInIBT The unclaimed yield of the user in IBT (not just the updated yield)
*/
function updateYield(address _user) external returns (uint256 updatedUserYieldInIBT);
/**
* @notice Claims caller's unclaimed yield in asset
* @param _receiver The receiver of yield
* @param _minAssets The minimum amount of assets that should be received
* @return yieldInAsset The amount of yield claimed in asset
*/
function claimYield(
address _receiver,
uint256 _minAssets
) external returns (uint256 yieldInAsset);
/**
* @notice Claims caller's unclaimed yield in IBT
* @param _receiver The receiver of yield
* @param _minIBT The minimum amount of IBT that should be received
* @return yieldInIBT The amount of yield claimed in IBT
*/
function claimYieldInIBT(
address _receiver,
uint256 _minIBT
) external returns (uint256 yieldInIBT);
/**
* @notice Claims the collected ibt fees and redeems them to the fee collector
* @param _minAssets The minimum amount of assets that should be received
* @return assets The amount of assets sent to the fee collector
*/
function claimFees(uint256 _minAssets) external returns (uint256 assets);
/**
* @notice Updates yield of both sender and receiver of YTs
* @param _from the sender of YTs
* @param _to the receiver of YTs
*/
function beforeYtTransfer(address _from, address _to) external;
/**
* Call the claimRewards function of the rewards contract
* @param data The optional data to be passed to the rewards contract
*/
function claimRewards(bytes memory data) external;
/* SETTERS
*****************************************************************************************************************/
/**
* @notice Stores PT and IBT rates at expiry. Ideally, it should be called the day of expiry
*/
function storeRatesAtExpiry() external;
/** Set a new Rewards Proxy
* @param _rewardsProxy The address of the new reward proxy
*/
function setRewardsProxy(address _rewardsProxy) external;
/* GETTERS
*****************************************************************************************************************/
/**
* @notice Returns the amount of shares minted for the theorical deposited amount of assets
* @param assets The amount of assets deposited
* @return The amount of shares minted
*/
function previewDeposit(uint256 assets) external view returns (uint256);
/**
* @notice Returns the amount of shares minted for the theorical deposited amount of IBT
* @param ibts The amount of IBT deposited
* @return The amount of shares minted
*/
function previewDepositIBT(uint256 ibts) external view returns (uint256);
/**
* @notice Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
* @param receiver The receiver of the shares
* @return The maximum amount of assets that can be deposited
*/
function maxDeposit(address receiver) external view returns (uint256);
/**
* @notice Returns the theorical amount of shares that need to be burnt to receive assets of underlying
* @param assets The amount of assets to receive
* @return The amount of shares burnt
*/
function previewWithdraw(uint256 assets) external view returns (uint256);
/**
* @notice Returns the theorical amount of shares that need to be burnt to receive amount of IBT
* @param ibts The amount of IBT to receive
* @return The amount of shares burnt
*/
function previewWithdrawIBT(uint256 ibts) external view returns (uint256);
/**
* @notice Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
* @param owner The owner of the Vault shares
* @return The maximum amount of assets that can be withdrawn
*/
function maxWithdraw(address owner) external view returns (uint256);
/**
* @notice Returns the maximum amount of the IBT that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
* @param owner The owner of the Vault shares
* @return The maximum amount of IBT that can be withdrawn
*/
function maxWithdrawIBT(address owner) external view returns (uint256);
/**
* @notice Returns the amount of assets received for the theorical amount of burnt shares
* @param shares The amount of shares to burn
* @return The amount of assets received
*/
function previewRedeem(uint256 shares) external view returns (uint256);
/**
* @notice Returns the amount of IBT received for the theorical amount of burnt shares
* @param shares The amount of shares to burn
* @return The amount of IBT received
*/
function previewRedeemForIBT(uint256 shares) external view returns (uint256);
/**
* @notice Returns the maximum amount of Vault shares that can be redeemed by the owner
* @notice This function behaves differently before and after expiry. Before expiry an equal amount of PT and YT
* needs to be burnt, while after expiry only PTs are burnt.
* @param owner The owner of the shares
* @return The maximum amount of shares that can be redeemed
*/
function maxRedeem(address owner) external view returns (uint256);
/**
* Returns the total amount of the underlying asset that is owned by the Vault in the form of IBT.
*/
function totalAssets() external view returns (uint256);
/**
* @notice Converts an underlying amount in principal. Equivalent to ERC-4626's convertToShares method.
* @param underlyingAmount The amount of underlying (or assets) to convert
* @return The resulting amount of principal (or shares)
*/
function convertToPrincipal(uint256 underlyingAmount) external view returns (uint256);
/**
* @notice Converts a principal amount in underlying. Equivalent to ERC-4626's convertToAssets method.
* @param principalAmount The amount of principal (or shares) to convert
* @return The resulting amount of underlying (or assets)
*/
function convertToUnderlying(uint256 principalAmount) external view returns (uint256);
/**
* @notice Returns whether or not the contract is paused.
* @return true if the contract is paused, and false otherwise
*/
function paused() external view returns (bool);
/**
* @notice Returns the unix timestamp (uint256) at which the PT contract expires
* @return The unix timestamp (uint256) when PTs become redeemable
*/
function maturity() external view returns (uint256);
/**
* @notice Returns the duration of the PT contract
* @return The duration (in s) to expiry/maturity of the PT contract
*/
function getDuration() external view returns (uint256);
/**
* @notice Returns the address of the underlying token (or asset). Equivalent to ERC-4626's asset method.
* @return The address of the underlying token (or asset)
*/
function underlying() external view returns (address);
/**
* @notice Returns the IBT address of the PT contract
* @return ibt The address of the IBT
*/
function getIBT() external view returns (address ibt);
/**
* @notice Returns the yt address of the PT contract
* @return yt The address of the yt
*/
function getYT() external view returns (address yt);
/**
* @notice Returns the current ibtRate
* @return The current ibtRate
*/
function getIBTRate() external view returns (uint256);
/**
* @notice Returns the current ptRate
* @return The current ptRate
*/
function getPTRate() external view returns (uint256);
/**
* @notice Returns 1 unit of IBT
* @return The IBT unit
*/
function getIBTUnit() external view returns (uint256);
/**
* @notice Get the unclaimed fees in IBT
* @return The unclaimed fees in IBT
*/
function getUnclaimedFeesInIBT() external view returns (uint256);
/**
* @notice Get the total collected fees in IBT (claimed and unclaimed)
* @return The total fees in IBT
*/
function getTotalFeesInIBT() external view returns (uint256);
/**
* @notice Get the tokenization fee of the PT
* @return The tokenization fee
*/
function getTokenizationFee() external view returns (uint256);
/**
* @notice Get the current IBT yield of the user
* @param _user The address of the user to get the current yield from
* @return The yield of the user in IBT
*/
function getCurrentYieldOfUserInIBT(address _user) external view returns (uint256);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
interface IStableSwapNG {
function A() external view returns (uint256);
function A_precise() external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function D_ma_time() external view returns (uint256);
function D_oracle() external view returns (uint256);
function N_COINS() external view returns (uint256);
function add_liquidity(
uint256[] memory _amounts,
uint256 _min_mint_amount,
address _receiver
) external returns (uint256);
function admin_balances(uint256 arg0) external view returns (uint256);
function admin_fee() external view returns (uint256);
function allowance(address arg0, address arg1) external view returns (uint256);
function approve(address _spender, uint256 _value) external returns (bool);
function balanceOf(address arg0) external view returns (uint256);
function balances(uint256 i) external view returns (uint256);
function calc_token_amount(
uint256[] memory _amounts,
bool _is_deposit
) external view returns (uint256);
function calc_withdraw_one_coin(uint256 _burn_amount, int128 i) external view returns (uint256);
function coins(uint256 arg0) external view returns (address);
function decimals() external view returns (uint8);
function dynamic_fee(int128 i, int128 j) external view returns (uint256);
function ema_price(uint256 i) external view returns (uint256);
function exchange(int128 i, int128 j, uint256 _dx, uint256 _min_dy) external returns (uint256);
function exchange(
int128 i,
int128 j,
uint256 _dx,
uint256 _min_dy,
address _receiver
) external returns (uint256);
function exchange_received(
int128 i,
int128 j,
uint256 _dx,
uint256 _min_dy
) external returns (uint256);
function exchange_received(
int128 i,
int128 j,
uint256 _dx,
uint256 _min_dy,
address _receiver
) external returns (uint256);
function fee() external view returns (uint256);
function future_A() external view returns (uint256);
function future_A_time() external view returns (uint256);
function get_balances() external view returns (uint256[] memory);
function get_dx(int128 i, int128 j, uint256 dy) external view returns (uint256);
function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256);
function get_p(uint256 i) external view returns (uint256);
function get_virtual_price() external view returns (uint256);
function initial_A() external view returns (uint256);
function initial_A_time() external view returns (uint256);
function last_price(uint256 i) external view returns (uint256);
function ma_exp_time() external view returns (uint256);
function ma_last_time() external view returns (uint256);
function name() external view returns (string memory);
function nonces(address arg0) external view returns (uint256);
function offpeg_fee_multiplier() external view returns (uint256);
function permit(
address _owner,
address _spender,
uint256 _value,
uint256 _deadline,
uint8 _v,
bytes32 _r,
bytes32 _s
) external returns (bool);
function price_oracle(uint256 i) external view returns (uint256);
function ramp_A(uint256 _future_A, uint256 _future_time) external;
function remove_liquidity(
uint256 _burn_amount,
uint256[] memory _min_amounts
) external returns (uint256[] memory);
function remove_liquidity(
uint256 _burn_amount,
uint256[] memory _min_amounts,
address _receiver
) external returns (uint256[] memory);
function remove_liquidity(
uint256 _burn_amount,
uint256[] memory _min_amounts,
address _receiver,
bool _claim_admin_fees
) external returns (uint256[] memory);
function remove_liquidity_imbalance(
uint256[] memory _amounts,
uint256 _max_burn_amount
) external returns (uint256);
function remove_liquidity_imbalance(
uint256[] memory _amounts,
uint256 _max_burn_amount,
address _receiver
) external returns (uint256);
function remove_liquidity_one_coin(
uint256 _burn_amount,
int128 i,
uint256 _min_received
) external returns (uint256);
function remove_liquidity_one_coin(
uint256 _burn_amount,
int128 i,
uint256 _min_received,
address _receiver
) external returns (uint256);
function salt() external view returns (bytes32);
function set_ma_exp_time(uint256 _ma_exp_time, uint256 _D_ma_time) external;
function set_new_fee(uint256 _new_fee, uint256 _new_offpeg_fee_multiplier) external;
function stop_ramp_A() external;
function stored_rates() external view returns (uint256[] memory);
function symbol() external view returns (string memory);
function totalSupply() external view returns (uint256);
function transfer(address _to, uint256 _value) external returns (bool);
function transferFrom(address _from, address _to, uint256 _value) external returns (bool);
function version() external view returns (string memory);
function withdraw_admin_fees() external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.20;
import {Math} from "openzeppelin-math/Math.sol";
import {IERC20} from "openzeppelin-contracts/interfaces/IERC20.sol";
import {IERC4626} from "openzeppelin-contracts/interfaces/IERC4626.sol";
import {ICurveNGPool} from "../interfaces/ICurveNGPool.sol";
import {IStableSwapNG} from "../interfaces/IStableSwapNG.sol";
import {IPrincipalToken} from "../interfaces/IPrincipalToken.sol";
/**
* @dev Utilities for computing prices of Spectra PTs, YTs and LP tokens in Curve CryptoSwap pools.
*/
library CurveOracleLib {
using Math for uint256;
error PoolLiquidityError();
uint256 public constant CURVE_UNIT = 1e18;
/**
* This function returns the TWAP rate PT/Asset on a Curve Cryptoswap pool, but takes into account the current rate of IBT
* This accounts for special cases where underlying asset becomes insolvent and has decreasing exchangeRate
* @param pool Address of the Curve Pool to get rate from
* @return PT/Underlying exchange rate
*/
function getPTToAssetRate(address pool) internal view returns (uint256) {
uint256 ptToIBTRate = getPTToIBTRate(pool);
IERC4626 ibt = IERC4626(ICurveNGPool(pool).coins(0));
return ibt.previewRedeem(ptToIBTRate);
}
/**
* This function returns the TWAP rate PT/Asset on a Curve StableSwap NG pool, but takes into account the current rate of IBT
* This accounts for special cases where underlying asset becomes insolvent and has decreasing exchangeRate
* @param pool Address of the Curve Pool to get rate from
* @return PT/Underlying exchange rate
*/
function getPTToAssetRateSNG(address pool) public view returns (uint256) {
uint256 ptToIBTRate = getPTToIBTRateSNG(pool);
IERC4626 ibt = IERC4626(ICurveNGPool(pool).coins(0));
return ibt.previewRedeem(ptToIBTRate);
}
/**
* @dev This function returns the TWAP rate PT/IBT on a Curve Cryptoswap pool
* This accounts for special cases where underlying asset becomes insolvent and has decreasing exchangeRate
* @param pool Address of the Curve Pool to get rate from
* @return PT/IBT exchange rate
*/
function getPTToIBTRate(address pool) internal view returns (uint256) {
IPrincipalToken pt = IPrincipalToken(ICurveNGPool(pool).coins(1));
uint256 maturity = pt.maturity();
if (maturity <= block.timestamp) {
return pt.previewRedeemForIBT(pt.getIBTUnit());
} else {
return pt.getIBTUnit().mulDiv(ICurveNGPool(pool).price_oracle(), CURVE_UNIT);
}
}
/**
* @dev This function returns the TWAP rate PT/IBT on a Curve StableSwap NG pool
* This accounts for special cases where underlying asset becomes insolvent and has decreasing exchangeRate
* @param pool Address of the Curve Pool to get rate from
* @return PT/IBT exchange rate
*/
function getPTToIBTRateSNG(address pool) public view returns (uint256) {
IPrincipalToken pt = IPrincipalToken(ICurveNGPool(pool).coins(1));
uint256 maturity = pt.maturity();
if (maturity <= block.timestamp) {
return pt.previewRedeemForIBT(pt.getIBTUnit());
} else {
uint256[] memory storedRates = IStableSwapNG(pool).stored_rates();
return
pt.getIBTUnit().mulDiv(storedRates[1], storedRates[0]).mulDiv(
IStableSwapNG(pool).price_oracle(0),
CURVE_UNIT
);
}
}
/**
* This function returns the TWAP rate YT/Asset on a Curve Cryptoswap pool
* @param pool Curve Pool to get rate from
* @return YT/Underlying exchange rate
*/
function getYTToAssetRate(address pool) internal view returns (uint256) {
IPrincipalToken pt = IPrincipalToken(ICurveNGPool(pool).coins(1));
uint256 ptToAssetRateCore = pt.previewRedeem(pt.getIBTUnit());
uint256 ptToAssetRateOracle = getPTToAssetRate(pool);
if (ptToAssetRateOracle > ptToAssetRateCore) {
revert PoolLiquidityError();
}
return (ptToAssetRateCore - ptToAssetRateOracle);
}
/**
* This function returns the TWAP rate YT/Asset on a Curve StableSwap NG pool
* @param pool Curve Pool to get rate from
* @return YT/Underlying exchange rate
*/
function getYTToAssetRateSNG(address pool) internal view returns (uint256) {
IPrincipalToken pt = IPrincipalToken(IStableSwapNG(pool).coins(1));
uint256 ptToAssetRateCore = pt.previewRedeem(pt.getIBTUnit());
uint256 ptToAssetRateOracle = getPTToAssetRateSNG(pool);
if (ptToAssetRateOracle > ptToAssetRateCore) {
revert PoolLiquidityError();
}
return (ptToAssetRateCore - ptToAssetRateOracle);
}
/**
* @dev This function returns the TWAP rate YT/IBT on a Curve Cryptoswap pool
* @param pool Curve Pool to get rate from
* @return YT/IBT exchange rate
*/
function getYTToIBTRate(address pool) internal view returns (uint256) {
IPrincipalToken pt = IPrincipalToken(ICurveNGPool(pool).coins(1));
uint256 ptToIBTRateCore = pt.previewRedeemForIBT(pt.getIBTUnit());
uint256 ptToIBTRateOracle = getPTToIBTRate(pool);
if (ptToIBTRateOracle > ptToIBTRateCore) {
revert PoolLiquidityError();
}
return ptToIBTRateCore - ptToIBTRateOracle;
}
/**
* @dev This function returns the TWAP rate YT/IBT on a Curve StableSwap NG pool
* @param pool Curve Pool to get rate from
* @return YT/IBT exchange rate
*/
function getYTToIBTRateSNG(address pool) internal view returns (uint256) {
IPrincipalToken pt = IPrincipalToken(IStableSwapNG(pool).coins(1));
uint256 ptToIBTRateCore = pt.previewRedeemForIBT(pt.getIBTUnit());
uint256 ptToIBTRateOracle = getPTToIBTRateSNG(pool);
if (ptToIBTRateOracle > ptToIBTRateCore) {
revert PoolLiquidityError();
}
return ptToIBTRateCore - ptToIBTRateOracle;
}
/**
* This function returns the TWAP rate LP/Asset on a Curve Cryptoswap , and takes into account the current rate of IBT
* @param pool Address of the Curve Pool to get rate from
* @return LP/Underlying exchange rate
*/
function getLPTToAssetRate(address pool) internal view returns (uint256) {
uint256 lptToIBTRate = getLPTToIBTRate(pool);
IERC4626 ibt = IERC4626(ICurveNGPool(pool).coins(0));
return ibt.previewRedeem(lptToIBTRate);
}
/**
* @dev This function returns the TWAP rate LP/IBT on a Curve CryptoSwap pool
* @param pool Address of the Curve Pool to get rate from
* @return LP/IBT exchange rate
*/
function getLPTToIBTRate(address pool) internal view returns (uint256) {
IPrincipalToken pt = IPrincipalToken(ICurveNGPool(pool).coins(1));
uint256 maturity = pt.maturity();
uint256 balIBT = ICurveNGPool(pool).balances(0);
uint256 balPT = ICurveNGPool(pool).balances(1);
uint256 supplyLPT = IERC20(pool).totalSupply();
if (maturity <= block.timestamp) {
return
pt.previewRedeemForIBT(balPT.mulDiv(CURVE_UNIT, supplyLPT)) +
balIBT.mulDiv(CURVE_UNIT, supplyLPT);
} else {
uint256 ptToIBTRate = getPTToIBTRate(pool);
return
((balPT.mulDiv(ptToIBTRate, pt.getIBTUnit())) + balIBT).mulDiv(
CURVE_UNIT,
supplyLPT
);
}
}
/**
* This function returns the TWAP rate LP/Asset on a Curve StableSwap NG pool, and takes into account the current rate of IBT
* @param pool Address of the Curve Pool to get rate from
* @return LP/Underlying exchange rate
*/
function getLPTToAssetRateSNG(address pool) internal view returns (uint256) {
uint256 lptToIBTRate = getLPTToIBTRateSNG(pool);
IERC4626 ibt = IERC4626(IStableSwapNG(pool).coins(0));
return ibt.previewRedeem(lptToIBTRate);
}
/**
* @dev This function returns the TWAP rate LP/IBT on a Curve StableSwap NG pool
* @param pool Address of the Curve Pool to get rate from
* @return LP/IBT exchange rate
*/
function getLPTToIBTRateSNG(address pool) internal view returns (uint256) {
IPrincipalToken pt = IPrincipalToken(IStableSwapNG(pool).coins(1));
uint256 maturity = pt.maturity();
uint256 balIBT = IStableSwapNG(pool).balances(0);
uint256 balPT = IStableSwapNG(pool).balances(1);
uint256 supplyLPT = IERC20(pool).totalSupply();
if (maturity <= block.timestamp) {
return
pt.previewRedeemForIBT(balPT.mulDiv(CURVE_UNIT, supplyLPT)) +
balIBT.mulDiv(CURVE_UNIT, supplyLPT);
} else {
uint256 ptToIBTRate = getPTToIBTRateSNG(pool);
return
((balPT.mulDiv(ptToIBTRate, pt.getIBTUnit())) + balIBT).mulDiv(
CURVE_UNIT,
supplyLPT
);
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.20;
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {CurveOracleLib} from "src/libraries/CurveOracleLib.sol";
import {BaseOracleCurveLPT} from "src/spectra-oracles/oracles/BaseOracleCurveLPT.sol";
import {Initializable} from "openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol";
/**
* @title BaseFeedCurveLPTAsset contract
* @author Spectra Finance
* @notice Base contract to implement the AggregatorV3Interface feed for the LPT price expressed in asset
*/
abstract contract BaseFeedCurveLPTAssetSNG is BaseOracleCurveLPT {
constructor() {
_disableInitializers();
}
/**
* @notice Initializes the oracle
* @param _pt The principal token address
* @param _pool The pool address
*/
function __BaseFeedCurveLPTAssetSNG_init(address _pt, address _pool) internal onlyInitializing {
super.__BaseOracleCurveLPT_init(_pt, _pool);
}
/* INTERNAL
*****************************************************************************************************************/
function _LPTPrice() internal view override returns (uint256) {
return CurveOracleLib.getLPTToAssetRateSNG(pool);
}
/* AGGREGATORV3INTERFACE
*****************************************************************************************************************/
function decimals() external view override returns (uint8) {
return IERC20Metadata(asset).decimals();
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.20;
import {Initializable} from "openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {IPrincipalToken} from "src/interfaces/IPrincipalToken.sol";
import {AggregatorV3Interface} from "src/interfaces/AggregatorV3Interface.sol";
/**
* @title BaseOracle contract
* @author Spectra Finance
* @notice A base oracle implementation
*/
abstract contract BaseOracle is AggregatorV3Interface, Initializable {
address public pool;
address public pt;
uint256 public maturity;
address public asset;
address public ibt;
constructor() {
_disableInitializers();
}
/**
* @notice First function to be called after deployment
* @param _pt The principal token address
* @param _pool The pool address
*/
function __BaseOracle_init(address _pt, address _pool) internal onlyInitializing {
pool = _pool;
pt = _pt;
maturity = IPrincipalToken(_pt).maturity();
asset = IPrincipalToken(_pt).underlying();
ibt = IPrincipalToken(_pt).getIBT();
}
/* AggregatorV3Interface
*****************************************************************************************************************/
/** @dev See {AggregatorV3Interface-version}. */
function version() external pure virtual returns (uint256) {
return 1;
}
/** @dev See {AggregatorV3Interface-decimals}. */
function decimals() external view virtual returns (uint8);
/** @dev See {AggregatorV3Interface-getQuoteAmount}. */
function _getQuoteAmount() internal view virtual returns (uint256);
/** @dev See {AggregatorV3Interface-getRoundData}. */
function getRoundData(
uint80
)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
)
{
return (0, int256(_getQuoteAmount()), 0, 0, 0);
}
/** @dev See {AggregatorV3Interface-latestRoundData}. */
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
)
{
return (0, int256(_getQuoteAmount()), 0, 0, 0);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.20;
import {BaseOracle} from "src/spectra-oracles/oracles/BaseOracle.sol";
import {Initializable} from "openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol";
/**
* @title BaseOracleCurveLPT contract
* @author Spectra Finance
* @notice A base oracle implementation for Curve LP Token
*/
abstract contract BaseOracleCurveLPT is BaseOracle {
constructor() {
_disableInitializers();
}
/**
* @notice Initializes the oracle
* @param _pt The principal token address
* @param _pool The pool address
*/
function __BaseOracleCurveLPT_init(address _pt, address _pool) internal onlyInitializing {
super.__BaseOracle_init(_pt, _pool);
}
/* INTERNAL
*****************************************************************************************************************/
/**
* @dev Returns the LPT Price of the pool in asset or IBT
*/
function _getQuoteAmount() internal view override returns (uint256) {
return _LPTPrice();
}
function _LPTPrice() internal view virtual returns (uint256);
}{
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"appendCBOR": true,
"bytecodeHash": "ipfs",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
"openzeppelin-erc20-basic/=lib/openzeppelin-contracts/contracts/token/ERC20/",
"openzeppelin-erc20-extensions/=lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/",
"openzeppelin-erc20/=lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/",
"openzeppelin-math/=lib/openzeppelin-contracts/contracts/utils/math/",
"openzeppelin-proxy/=lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/",
"openzeppelin-utils/=lib/openzeppelin-contracts/contracts/utils/",
"config/=lib/spectra-contracts-configs/script/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"DiamondRouter/=lib/DiamondRouter/",
"halmos-cheatcodes/=lib/DiamondRouter/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
"solidity-stringutils/=lib/DiamondRouter/lib/solidity-stringutils/",
"spectra-contracts-configs/=lib/spectra-contracts-configs/"
],
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","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"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint80","name":"","type":"uint80"}],"name":"getRoundData","outputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ibt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pt","type":"address"},{"internalType":"address","name":"_pool","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"latestRoundData","outputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maturity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
608060405234801561000f575f80fd5b50610018610035565b610020610035565b610028610035565b610030610035565b6100e7565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100855760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100e45780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6111fb806100f45f395ff3fe608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80637284e41611610088578063c43f357b11610063578063c43f357b1461020f578063dc26302214610222578063f2fde38b14610235578063feaf968c14610248575f80fd5b80637284e416146101805780638da5cb5b146101955780639a6fc8f5146101c5575f80fd5b806338d52e0f116100c357806338d52e0f14610149578063485cc9551461015c57806354fd4d5014610171578063715018a614610178575f80fd5b806316f0115b146100e9578063204f83f914610118578063313ce5671461012f575b5f80fd5b5f546100fb906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61012160025481565b60405190815260200161010f565b610137610250565b60405160ff909116815260200161010f565b6003546100fb906001600160a01b031681565b61016f61016a366004610f73565b6102c0565b005b6001610121565b61016f6103d0565b6101886103e3565b60405161010f9190610faa565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03166100fb565b6101d86101d3366004610ff5565b6103ff565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a00161010f565b6004546100fb906001600160a01b031681565b6001546100fb906001600160a01b031681565b61016f61024336600461101e565b610420565b6101d8610462565b6003546040805163313ce56760e01b815290515f926001600160a01b03169163313ce5679160048083019260209291908290030181865afa158015610297573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102bb9190611039565b905090565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff165f811580156103055750825b90505f8267ffffffffffffffff1660011480156103215750303b155b90508115801561032f575080155b1561034d5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561037757845460ff60401b1916600160401b1785555b6103818787610482565b83156103c757845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6103d8610498565b6103e15f6104f3565b565b6040518060600160405280602c815260200161119a602c913981565b5f805f805f8061040d610563565b90979096505f9550859450849350915050565b610428610498565b6001600160a01b03811661045657604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61045f816104f3565b50565b5f805f805f80610470610563565b90969095505f94508493508392509050565b61048a61056c565b61049482826105b5565b5050565b336104ca7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146103e15760405163118cdaa760e01b815233600482015260240161044d565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f6102bb6105c7565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166103e157604051631afcd79f60e31b815260040160405180910390fd5b6105bd61056c565b61049482826105dc565b5f80546102bb906001600160a01b031661077d565b6105e461056c565b5f80546001600160a01b038084166001600160a01b0319928316179092556001805492851692909116821790556040805163204f83f960e01b8152905163204f83f9916004808201926020929091908290030181865afa15801561064a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061066e9190611059565b600281905550816001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106d49190611070565b60035f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b031663c644fe946040518163ffffffff1660e01b8152600401602060405180830381865afa158015610735573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107599190611070565b600480546001600160a01b0319166001600160a01b03929092169190911790555050565b5f8061078883610866565b60405163c661065760e01b81525f600482018190529192506001600160a01b0385169063c661065790602401602060405180830381865afa1580156107cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107f39190611070565b60405163266d6a8360e11b8152600481018490529091506001600160a01b03821690634cdad506906024015b602060405180830381865afa15801561083a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061085e9190611059565b949350505050565b60405163c661065760e01b8152600160048201525f9081906001600160a01b0384169063c661065790602401602060405180830381865afa1580156108ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108d19190611070565b90505f816001600160a01b031663204f83f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610910573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109349190611059565b604051634903b0d160e01b81525f600482018190529192506001600160a01b03861690634903b0d190602401602060405180830381865afa15801561097b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061099f9190611059565b604051634903b0d160e01b8152600160048201529091505f906001600160a01b03871690634903b0d190602401602060405180830381865afa1580156109e7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0b9190611059565b90505f866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a4a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6e9190611059565b9050428411610b1e57610a8a83670de0b6b3a764000083610bc1565b6001600160a01b0386166368c1f7f6610aac85670de0b6b3a764000086610bc1565b6040518263ffffffff1660e01b8152600401610aca91815260200190565b602060405180830381865afa158015610ae5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b099190611059565b610b13919061108b565b979650505050505050565b5f610b2888610c81565b9050610bb5670de0b6b3a76400008386610ba4858b6001600160a01b0316631f2b4f246040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b78573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9c9190611059565b899190610bc1565b610bae919061108b565b9190610bc1565b98975050505050505050565b5f838302815f1985870982811083820303915050805f03610bf557838281610beb57610beb6110b0565b0492505050610c7a565b808411610c155760405163227bc15360e01b815260040160405180910390fd5b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60405163c661065760e01b8152600160048201525f9081906001600160a01b0384169063c661065790602401602060405180830381865afa158015610cc8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cec9190611070565b90505f816001600160a01b031663204f83f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d2b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d4f9190611059565b9050428111610de557816001600160a01b03166368c1f7f6836001600160a01b0316631f2b4f246040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dc79190611059565b6040518263ffffffff1660e01b815260040161081f91815260200190565b5f846001600160a01b031663fd0684b16040518163ffffffff1660e01b81526004015f60405180830381865afa158015610e21573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e4891908101906110d8565b604051636872765360e01b81525f6004820152909150610f56906001600160a01b03871690636872765390602401602060405180830381865afa158015610e91573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eb59190611059565b670de0b6b3a7640000610bae84600181518110610ed457610ed4611185565b6020026020010151855f81518110610eee57610eee611185565b6020026020010151886001600160a01b0316631f2b4f246040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f32573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bae9190611059565b95945050505050565b6001600160a01b038116811461045f575f80fd5b5f8060408385031215610f84575f80fd5b8235610f8f81610f5f565b91506020830135610f9f81610f5f565b809150509250929050565b5f6020808352835180828501525f5b81811015610fd557858101830151858201604001528201610fb9565b505f604082860101526040601f19601f8301168501019250505092915050565b5f60208284031215611005575f80fd5b813569ffffffffffffffffffff81168114610c7a575f80fd5b5f6020828403121561102e575f80fd5b8135610c7a81610f5f565b5f60208284031215611049575f80fd5b815160ff81168114610c7a575f80fd5b5f60208284031215611069575f80fd5b5051919050565b5f60208284031215611080575f80fd5b8151610c7a81610f5f565b808201808211156110aa57634e487b7160e01b5f52601160045260245ffd5b92915050565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b5f60208083850312156110e9575f80fd5b825167ffffffffffffffff80821115611100575f80fd5b818501915085601f830112611113575f80fd5b815181811115611125576111256110c4565b8060051b604051601f19603f8301168101818110858211171561114a5761114a6110c4565b604052918252848201925083810185019188831115611167575f80fd5b938501935b82851015610bb55784518452938501939285019261116c565b634e487b7160e01b5f52603260045260245ffdfe4942542f505420437572766520506f6f6c204f7261636c653a204c505420707269636520696e206173736574a2646970667358221220dcd59328c8fc8fb3fa1fefddffc4a1c270b62c64f5d87694f05ce1891cab3d8064736f6c63430008140033
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80637284e41611610088578063c43f357b11610063578063c43f357b1461020f578063dc26302214610222578063f2fde38b14610235578063feaf968c14610248575f80fd5b80637284e416146101805780638da5cb5b146101955780639a6fc8f5146101c5575f80fd5b806338d52e0f116100c357806338d52e0f14610149578063485cc9551461015c57806354fd4d5014610171578063715018a614610178575f80fd5b806316f0115b146100e9578063204f83f914610118578063313ce5671461012f575b5f80fd5b5f546100fb906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61012160025481565b60405190815260200161010f565b610137610250565b60405160ff909116815260200161010f565b6003546100fb906001600160a01b031681565b61016f61016a366004610f73565b6102c0565b005b6001610121565b61016f6103d0565b6101886103e3565b60405161010f9190610faa565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03166100fb565b6101d86101d3366004610ff5565b6103ff565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a00161010f565b6004546100fb906001600160a01b031681565b6001546100fb906001600160a01b031681565b61016f61024336600461101e565b610420565b6101d8610462565b6003546040805163313ce56760e01b815290515f926001600160a01b03169163313ce5679160048083019260209291908290030181865afa158015610297573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102bb9190611039565b905090565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff165f811580156103055750825b90505f8267ffffffffffffffff1660011480156103215750303b155b90508115801561032f575080155b1561034d5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561037757845460ff60401b1916600160401b1785555b6103818787610482565b83156103c757845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6103d8610498565b6103e15f6104f3565b565b6040518060600160405280602c815260200161119a602c913981565b5f805f805f8061040d610563565b90979096505f9550859450849350915050565b610428610498565b6001600160a01b03811661045657604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61045f816104f3565b50565b5f805f805f80610470610563565b90969095505f94508493508392509050565b61048a61056c565b61049482826105b5565b5050565b336104ca7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146103e15760405163118cdaa760e01b815233600482015260240161044d565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f6102bb6105c7565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166103e157604051631afcd79f60e31b815260040160405180910390fd5b6105bd61056c565b61049482826105dc565b5f80546102bb906001600160a01b031661077d565b6105e461056c565b5f80546001600160a01b038084166001600160a01b0319928316179092556001805492851692909116821790556040805163204f83f960e01b8152905163204f83f9916004808201926020929091908290030181865afa15801561064a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061066e9190611059565b600281905550816001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106d49190611070565b60035f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b031663c644fe946040518163ffffffff1660e01b8152600401602060405180830381865afa158015610735573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107599190611070565b600480546001600160a01b0319166001600160a01b03929092169190911790555050565b5f8061078883610866565b60405163c661065760e01b81525f600482018190529192506001600160a01b0385169063c661065790602401602060405180830381865afa1580156107cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107f39190611070565b60405163266d6a8360e11b8152600481018490529091506001600160a01b03821690634cdad506906024015b602060405180830381865afa15801561083a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061085e9190611059565b949350505050565b60405163c661065760e01b8152600160048201525f9081906001600160a01b0384169063c661065790602401602060405180830381865afa1580156108ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108d19190611070565b90505f816001600160a01b031663204f83f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610910573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109349190611059565b604051634903b0d160e01b81525f600482018190529192506001600160a01b03861690634903b0d190602401602060405180830381865afa15801561097b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061099f9190611059565b604051634903b0d160e01b8152600160048201529091505f906001600160a01b03871690634903b0d190602401602060405180830381865afa1580156109e7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0b9190611059565b90505f866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a4a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6e9190611059565b9050428411610b1e57610a8a83670de0b6b3a764000083610bc1565b6001600160a01b0386166368c1f7f6610aac85670de0b6b3a764000086610bc1565b6040518263ffffffff1660e01b8152600401610aca91815260200190565b602060405180830381865afa158015610ae5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b099190611059565b610b13919061108b565b979650505050505050565b5f610b2888610c81565b9050610bb5670de0b6b3a76400008386610ba4858b6001600160a01b0316631f2b4f246040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b78573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9c9190611059565b899190610bc1565b610bae919061108b565b9190610bc1565b98975050505050505050565b5f838302815f1985870982811083820303915050805f03610bf557838281610beb57610beb6110b0565b0492505050610c7a565b808411610c155760405163227bc15360e01b815260040160405180910390fd5b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60405163c661065760e01b8152600160048201525f9081906001600160a01b0384169063c661065790602401602060405180830381865afa158015610cc8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cec9190611070565b90505f816001600160a01b031663204f83f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d2b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d4f9190611059565b9050428111610de557816001600160a01b03166368c1f7f6836001600160a01b0316631f2b4f246040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dc79190611059565b6040518263ffffffff1660e01b815260040161081f91815260200190565b5f846001600160a01b031663fd0684b16040518163ffffffff1660e01b81526004015f60405180830381865afa158015610e21573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e4891908101906110d8565b604051636872765360e01b81525f6004820152909150610f56906001600160a01b03871690636872765390602401602060405180830381865afa158015610e91573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eb59190611059565b670de0b6b3a7640000610bae84600181518110610ed457610ed4611185565b6020026020010151855f81518110610eee57610eee611185565b6020026020010151886001600160a01b0316631f2b4f246040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f32573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bae9190611059565b95945050505050565b6001600160a01b038116811461045f575f80fd5b5f8060408385031215610f84575f80fd5b8235610f8f81610f5f565b91506020830135610f9f81610f5f565b809150509250929050565b5f6020808352835180828501525f5b81811015610fd557858101830151858201604001528201610fb9565b505f604082860101526040601f19601f8301168501019250505092915050565b5f60208284031215611005575f80fd5b813569ffffffffffffffffffff81168114610c7a575f80fd5b5f6020828403121561102e575f80fd5b8135610c7a81610f5f565b5f60208284031215611049575f80fd5b815160ff81168114610c7a575f80fd5b5f60208284031215611069575f80fd5b5051919050565b5f60208284031215611080575f80fd5b8151610c7a81610f5f565b808201808211156110aa57634e487b7160e01b5f52601160045260245ffd5b92915050565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b5f60208083850312156110e9575f80fd5b825167ffffffffffffffff80821115611100575f80fd5b818501915085601f830112611113575f80fd5b815181811115611125576111256110c4565b8060051b604051601f19603f8301168101818110858211171561114a5761114a6110c4565b604052918252848201925083810185019188831115611167575f80fd5b938501935b82851015610bb55784518452938501939285019261116c565b634e487b7160e01b5f52603260045260245ffdfe4942542f505420437572766520506f6f6c204f7261636c653a204c505420707269636520696e206173736574a2646970667358221220dcd59328c8fc8fb3fa1fefddffc4a1c270b62c64f5d87694f05ce1891cab3d8064736f6c63430008140033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| SONIC | 100.00% | $0.092478 | 132.79 | $12.28 |
Loading...
Loading
Loading...
Loading
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.