Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
Operator
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 1000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {Ownable, Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import {Currency, CurrencyLibrary} from "clober-dex/v2-core/libraries/Currency.sol"; import "./interfaces/ISimpleOracleStrategy.sol"; import "./interfaces/ILiquidityVault.sol"; import {IDatastreamOracle} from "./interfaces/IDatastreamOracle.sol"; contract Operator is UUPSUpgradeable, Initializable, Ownable2Step { using CurrencyLibrary for Currency; ILiquidityVault public immutable liquidityVault; IDatastreamOracle public immutable datastreamOracle; uint256 public requestFeeAmount; constructor(ILiquidityVault liquidityVault_, IDatastreamOracle datastreamOracle_) Ownable(msg.sender) { liquidityVault = liquidityVault_; datastreamOracle = datastreamOracle_; } function initialize(address initialOwner, uint256 requestFeeAmount_) external initializer { _transferOwnership(initialOwner); requestFeeAmount = requestFeeAmount_; } function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} function updatePosition(bytes32 key, uint256 oraclePrice, Tick tickA, Tick tickB, uint24 rate) external onlyOwner { ISimpleOracleStrategy oracleStrategy = ISimpleOracleStrategy(address(liquidityVault.getPool(key).strategy)); if (oracleStrategy.isPaused(key)) { oracleStrategy.unpause(key); } oracleStrategy.updatePosition(key, oraclePrice, tickA, tickB, rate); liquidityVault.rebalance(key); } function pause(bytes32 key) external onlyOwner { ISimpleOracleStrategy(address(liquidityVault.getPool(key).strategy)).pause(key); liquidityVault.rebalance(key); } function requestOraclePublic() external { address feeToken = datastreamOracle.feeToken(); IERC20(feeToken).transferFrom(msg.sender, address(this), requestFeeAmount); datastreamOracle.request(type(uint256).max); } function requestOracle(uint256 bitmap) external onlyOwner { datastreamOracle.request(bitmap); } function withdraw(Currency currency, address to, uint256 amount) external onlyOwner { currency.transfer(to, amount); } function setRequestFeeAmount(uint256 requestFeeAmount_) external onlyOwner { requestFeeAmount = requestFeeAmount_; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * 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 Ownable is Context { address private _owner; /** * @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. */ constructor(address initialOwner) { 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) { 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 { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {Ownable} from "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This extension of the {Ownable} contract includes a two-step mechanism to transfer * ownership, where the new owner must call {acceptOwnership} in order to replace the * old one. This can help prevent common mistakes, such as transfers of ownership to * incorrect accounts, or to contracts that are unable to interact with the * permission system. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. * * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.20; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.22; import {IBeacon} from "../beacon/IBeacon.sol"; import {IERC1967} from "../../interfaces/IERC1967.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This library provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots. */ library ERC1967Utils { /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the ERC-1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit IERC1967.Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the ERC-1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit IERC1967.AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the ERC-1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit IERC1967.BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// 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.1.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.22; import {IERC1822Proxiable} from "../../interfaces/draft-IERC1822.sol"; import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. */ abstract contract UUPSUpgradeable is IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable __self = address(this); /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev The call is from an unauthorized context. */ error UUPSUnauthorizedCallContext(); /** * @dev The storage `slot` is unsupported as a UUID. */ error UUPSUnsupportedProxiableUUID(bytes32 slot); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { _checkProxy(); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { _checkNotDelegated(); _; } /** * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data); } /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC-1967 compliant implementation pointing to self. * See {_onlyProxy}. */ function _checkProxy() internal view virtual { if ( address(this) == __self || // Must be called through delegatecall ERC1967Utils.getImplementation() != __self // Must be called through an active proxy ) { revert UUPSUnauthorizedCallContext(); } } /** * @dev Reverts if the execution is performed via delegatecall. * See {notDelegated}. */ function _checkNotDelegated() internal view virtual { if (address(this) != __self) { // Must not be called through delegatecall revert UUPSUnauthorizedCallContext(); } } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. * * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value * is expected to be the implementation slot in ERC-1967. * * Emits an {IERC1967-Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { revert UUPSUnsupportedProxiableUUID(slot); } ERC1967Utils.upgradeToAndCall(newImplementation, data); } catch { // The implementation is not UUPS revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.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 ERC-20 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.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.20; import {IERC721} from "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC-721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC-721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or * {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the address zero. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC-1967 implementation slot: * ```solidity * contract ERC1967 { * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * TIP: Consider using this library along with {SlotDerivation}. */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct Int256Slot { int256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Int256Slot` with member `value` located at `slot`. */ function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } /** * @dev Returns a `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC721Metadata} from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; import {BookId} from "../libraries/BookId.sol"; import {Currency} from "../libraries/Currency.sol"; import {OrderId} from "../libraries/OrderId.sol"; import {Tick} from "../libraries/Tick.sol"; import {FeePolicy} from "../libraries/FeePolicy.sol"; import {IERC721Permit} from "./IERC721Permit.sol"; import {IHooks} from "./IHooks.sol"; /** * @title IBookManager * @notice The interface for the BookManager contract */ interface IBookManager is IERC721Metadata, IERC721Permit { error InvalidUnitSize(); error InvalidFeePolicy(); error InvalidProvider(address provider); error LockedBy(address locker, address hook); error CurrencyNotSettled(); /** * @notice Event emitted when a new book is opened * @param id The book id * @param base The base currency * @param quote The quote currency * @param unitSize The unit size of the book * @param makerPolicy The maker fee policy * @param takerPolicy The taker fee policy * @param hooks The hooks contract */ event Open( BookId indexed id, Currency indexed base, Currency indexed quote, uint64 unitSize, FeePolicy makerPolicy, FeePolicy takerPolicy, IHooks hooks ); /** * @notice Event emitted when a new order is made * @param bookId The book id * @param user The user address * @param tick The order tick * @param orderIndex The order index * @param unit The order unit * @param provider The provider address */ event Make( BookId indexed bookId, address indexed user, Tick tick, uint256 orderIndex, uint64 unit, address provider ); /** * @notice Event emitted when an order is taken * @param bookId The book id * @param user The user address * @param tick The order tick * @param unit The order unit */ event Take(BookId indexed bookId, address indexed user, Tick tick, uint64 unit); /** * @notice Event emitted when an order is canceled * @param orderId The order id * @param unit The canceled unit */ event Cancel(OrderId indexed orderId, uint64 unit); /** * @notice Event emitted when an order is claimed * @param orderId The order id * @param unit The claimed unit */ event Claim(OrderId indexed orderId, uint64 unit); /** * @notice Event emitted when a provider is whitelisted * @param provider The provider address */ event Whitelist(address indexed provider); /** * @notice Event emitted when a provider is delisted * @param provider The provider address */ event Delist(address indexed provider); /** * @notice Event emitted when a provider collects fees * @param provider The provider address * @param recipient The recipient address * @param currency The currency * @param amount The collected amount */ event Collect(address indexed provider, address indexed recipient, Currency indexed currency, uint256 amount); /** * @notice Event emitted when new default provider is set * @param newDefaultProvider The new default provider address */ event SetDefaultProvider(address indexed newDefaultProvider); /** * @notice This structure represents a unique identifier for a book in the BookManager. * @param base The base currency of the book * @param unitSize The unit size of the book * @param quote The quote currency of the book * @param makerPolicy The maker fee policy of the book * @param hooks The hooks contract of the book * @param takerPolicy The taker fee policy of the book */ struct BookKey { Currency base; uint64 unitSize; Currency quote; FeePolicy makerPolicy; IHooks hooks; FeePolicy takerPolicy; } /** * @notice Returns the base URI * @return The base URI */ function baseURI() external view returns (string memory); /** * @notice Returns the contract URI * @return The contract URI */ function contractURI() external view returns (string memory); /** * @notice Returns the default provider * @return The default provider */ function defaultProvider() external view returns (address); /** * @notice Returns the total reserves of a given currency * @param currency The currency in question * @return The total reserves amount */ function reservesOf(Currency currency) external view returns (uint256); /** * @notice Checks if a provider is whitelisted * @param provider The address of the provider * @return True if the provider is whitelisted, false otherwise */ function isWhitelisted(address provider) external view returns (bool); /** * @notice Verifies if an owner has authorized a spender for a token * @param owner The address of the token owner * @param spender The address of the spender * @param tokenId The token ID */ function checkAuthorized(address owner, address spender, uint256 tokenId) external view; /** * @notice Calculates the amount owed to a provider in a given currency * @param provider The provider's address * @param currency The currency in question * @return The owed amount */ function tokenOwed(address provider, Currency currency) external view returns (uint256); /** * @notice Calculates the currency balance changes for a given locker * @param locker The address of the locker * @param currency The currency in question * @return The net change in currency balance */ function getCurrencyDelta(address locker, Currency currency) external view returns (int256); /** * @notice Retrieves the book key for a given book ID * @param id The book ID * @return The book key */ function getBookKey(BookId id) external view returns (BookKey memory); /** * @notice This structure represents a current status for an order in the BookManager. * @param provider The provider of the order * @param open The open unit of the order * @param claimable The claimable unit of the order */ struct OrderInfo { address provider; uint64 open; uint64 claimable; } /** * @notice Provides information about an order * @param id The order ID * @return Order information including provider, open status, and claimable unit */ function getOrder(OrderId id) external view returns (OrderInfo memory); /** * @notice Retrieves the locker and caller addresses for a given lock * @param i The index of the lock * @return locker The locker's address * @return lockCaller The caller's address */ function getLock(uint256 i) external view returns (address locker, address lockCaller); /** * @notice Provides the lock data * @return The lock data including necessary numeric values */ function getLockData() external view returns (uint128, uint128); /** * @notice Returns the depth of a given book ID and tick * @param id The book ID * @param tick The tick * @return The depth of the tick */ function getDepth(BookId id, Tick tick) external view returns (uint64); /** * @notice Retrieves the highest tick for a given book ID * @param id The book ID * @return tick The highest tick */ function getHighest(BookId id) external view returns (Tick tick); /** * @notice Finds the maximum tick less than a specified tick in a book * @dev Returns `Tick.wrap(type(int24).min)` if the specified tick is the lowest * @param id The book ID * @param tick The specified tick * @return The next lower tick */ function maxLessThan(BookId id, Tick tick) external view returns (Tick); /** * @notice Checks if a book is opened * @param id The book ID * @return True if the book is opened, false otherwise */ function isOpened(BookId id) external view returns (bool); /** * @notice Checks if a book is empty * @param id The book ID * @return True if the book is empty, false otherwise */ function isEmpty(BookId id) external view returns (bool); /** * @notice Encodes a BookKey into a BookId * @param key The BookKey to encode * @return The encoded BookId */ function encodeBookKey(BookKey calldata key) external pure returns (BookId); /** * @notice Loads a value from a specific storage slot * @param slot The storage slot * @return The value in the slot */ function load(bytes32 slot) external view returns (bytes32); /** * @notice Loads a sequence of values starting from a specific slot * @param startSlot The starting slot * @param nSlot The number of slots to load * @return The sequence of values */ function load(bytes32 startSlot, uint256 nSlot) external view returns (bytes memory); /** * @notice Opens a new book * @param key The book key * @param hookData The hook data */ function open(BookKey calldata key, bytes calldata hookData) external; /** * @notice Locks a book manager function * @param locker The locker address * @param data The lock data * @return The lock return data */ function lock(address locker, bytes calldata data) external returns (bytes memory); /** * @notice This structure represents the parameters for making an order. * @param key The book key for the order * @param tick The tick for the order * @param unit The unit for the order. Times key.unitSize to get actual bid amount. * @param provider The provider for the order. The limit order service provider address to collect fees. */ struct MakeParams { BookKey key; Tick tick; uint64 unit; address provider; } /** * @notice Make a limit order * @param params The order parameters * @param hookData The hook data * @return id The order id. Returns 0 if the order is not settled * @return quoteAmount The amount of quote currency to be paid */ function make(MakeParams calldata params, bytes calldata hookData) external returns (OrderId id, uint256 quoteAmount); /** * @notice This structure represents the parameters for taking orders in the specified tick. * @param key The book key for the order * @param tick The tick for the order * @param maxUnit The max unit to take */ struct TakeParams { BookKey key; Tick tick; uint64 maxUnit; } /** * @notice Take a limit order at specific tick * @param params The order parameters * @param hookData The hook data * @return quoteAmount The amount of quote currency to be received * @return baseAmount The amount of base currency to be paid */ function take(TakeParams calldata params, bytes calldata hookData) external returns (uint256 quoteAmount, uint256 baseAmount); /** * @notice This structure represents the parameters for canceling an order. * @param id The order id for the order * @param toUnit The remaining open unit for the order after cancellation. Must not exceed the current open unit. */ struct CancelParams { OrderId id; uint64 toUnit; } /** * @notice Cancel a limit order * @param params The order parameters * @param hookData The hook data * @return canceledAmount The amount of quote currency canceled */ function cancel(CancelParams calldata params, bytes calldata hookData) external returns (uint256 canceledAmount); /** * @notice Claims an order * @param id The order ID * @param hookData The hook data * @return claimedAmount The amount claimed */ function claim(OrderId id, bytes calldata hookData) external returns (uint256 claimedAmount); /** * @notice Collects fees from a provider * @param recipient The recipient address * @param currency The currency * @return The collected amount */ function collect(address recipient, Currency currency) external returns (uint256); /** * @notice Withdraws a currency * @param currency The currency * @param to The recipient address * @param amount The amount */ function withdraw(Currency currency, address to, uint256 amount) external; /** * @notice Settles a currency * @param currency The currency * @return The settled amount */ function settle(Currency currency) external payable returns (uint256); /** * @notice Whitelists a provider * @param provider The provider address */ function whitelist(address provider) external; /** * @notice Delists a provider * @param provider The provider address */ function delist(address provider) external; /** * @notice Sets the default provider * @param newDefaultProvider The new default provider address */ function setDefaultProvider(address newDefaultProvider) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; /** * @title IERC721Permit * @notice An interface for the ERC721 permit extension */ interface IERC721Permit is IERC721 { error InvalidSignature(); error PermitExpired(); /** * @notice The EIP-712 typehash for the permit struct used by the contract */ function PERMIT_TYPEHASH() external pure returns (bytes32); /** * @notice The EIP-712 domain separator for this contract */ function DOMAIN_SEPARATOR() external view returns (bytes32); /** * @notice Approve the spender to transfer the given tokenId * @param spender The address to approve * @param tokenId The tokenId to approve * @param deadline The deadline for the signature * @param v The recovery id of the signature * @param r The r value of the signature * @param s The s value of the signature */ function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; /** * @notice Get the current nonce for a token * @param tokenId The tokenId to get the nonce for * @return The current nonce */ function nonces(uint256 tokenId) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IBookManager} from "./IBookManager.sol"; import {OrderId} from "../libraries/OrderId.sol"; /** * @title IHooks * @notice Interface for the hooks contract */ interface IHooks { /** * @notice Hook called before opening a new book * @param sender The sender of the open transaction * @param key The key of the book being opened * @param hookData The data passed to the hook * @return Returns the function selector if the hook is successful */ function beforeOpen(address sender, IBookManager.BookKey calldata key, bytes calldata hookData) external returns (bytes4); /** * @notice Hook called after opening a new book * @param sender The sender of the open transaction * @param key The key of the book being opened * @param hookData The data passed to the hook * @return Returns the function selector if the hook is successful */ function afterOpen(address sender, IBookManager.BookKey calldata key, bytes calldata hookData) external returns (bytes4); /** * @notice Hook called before making a new order * @param sender The sender of the make transaction * @param params The parameters of the make transaction * @param hookData The data passed to the hook * @return Returns the function selector if the hook is successful */ function beforeMake(address sender, IBookManager.MakeParams calldata params, bytes calldata hookData) external returns (bytes4); /** * @notice Hook called after making a new order * @param sender The sender of the make transaction * @param params The parameters of the make transaction * @param orderId The id of the order that was made * @param hookData The data passed to the hook * @return Returns the function selector if the hook is successful */ function afterMake( address sender, IBookManager.MakeParams calldata params, OrderId orderId, bytes calldata hookData ) external returns (bytes4); /** * @notice Hook called before taking an order * @param sender The sender of the take transaction * @param params The parameters of the take transaction * @param hookData The data passed to the hook * @return Returns the function selector if the hook is successful */ function beforeTake(address sender, IBookManager.TakeParams calldata params, bytes calldata hookData) external returns (bytes4); /** * @notice Hook called after taking an order * @param sender The sender of the take transaction * @param params The parameters of the take transaction * @param takenUnit The unit that was taken * @param hookData The data passed to the hook * @return Returns the function selector if the hook is successful */ function afterTake( address sender, IBookManager.TakeParams calldata params, uint64 takenUnit, bytes calldata hookData ) external returns (bytes4); /** * @notice Hook called before canceling an order * @param sender The sender of the cancel transaction * @param params The parameters of the cancel transaction * @param hookData The data passed to the hook * @return Returns the function selector if the hook is successful */ function beforeCancel(address sender, IBookManager.CancelParams calldata params, bytes calldata hookData) external returns (bytes4); /** * @notice Hook called after canceling an order * @param sender The sender of the cancel transaction * @param params The parameters of the cancel transaction * @param canceledUnit The unit that was canceled * @param hookData The data passed to the hook * @return Returns the function selector if the hook is successful */ function afterCancel( address sender, IBookManager.CancelParams calldata params, uint64 canceledUnit, bytes calldata hookData ) external returns (bytes4); /** * @notice Hook called before claiming an order * @param sender The sender of the claim transaction * @param orderId The id of the order being claimed * @param hookData The data passed to the hook * @return Returns the function selector if the hook is successful */ function beforeClaim(address sender, OrderId orderId, bytes calldata hookData) external returns (bytes4); /** * @notice Hook called after claiming an order * @param sender The sender of the claim transaction * @param orderId The id of the order being claimed * @param claimedUnit The unit that was claimed * @param hookData The data passed to the hook * @return Returns the function selector if the hook is successful */ function afterClaim(address sender, OrderId orderId, uint64 claimedUnit, bytes calldata hookData) external returns (bytes4); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.20; import {IBookManager} from "../interfaces/IBookManager.sol"; type BookId is uint192; library BookIdLibrary { function toId(IBookManager.BookKey memory bookKey) internal pure returns (BookId id) { bytes32 hash = keccak256(abi.encode(bookKey)); assembly { id := and(hash, 0xffffffffffffffffffffffffffffffffffffffffffffffff) } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; type Currency is address; /// @title CurrencyLibrary /// @dev This library allows for transferring and holding native tokens and ERC20 tokens library CurrencyLibrary { using CurrencyLibrary for Currency; /// @notice Thrown when a native transfer fails error NativeTransferFailed(); /// @notice Thrown when an ERC20 transfer fails error ERC20TransferFailed(); Currency public constant NATIVE = Currency.wrap(address(0)); function transfer(Currency currency, address to, uint256 amount) internal { // implementation from // https://github.com/transmissions11/solmate/blob/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/SafeTransferLib.sol bool success; if (currency.isNative()) { assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } if (!success) revert NativeTransferFailed(); } else { assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), currency, 0, freeMemoryPointer, 68, 0, 32) ) } if (!success) revert ERC20TransferFailed(); } } function balanceOfSelf(Currency currency) internal view returns (uint256) { if (currency.isNative()) return address(this).balance; else return IERC20(Currency.unwrap(currency)).balanceOf(address(this)); } function equals(Currency currency, Currency other) internal pure returns (bool) { return Currency.unwrap(currency) == Currency.unwrap(other); } function isNative(Currency currency) internal pure returns (bool) { return Currency.unwrap(currency) == Currency.unwrap(NATIVE); } function toId(Currency currency) internal pure returns (uint256) { return uint160(Currency.unwrap(currency)); } function fromId(uint256 id) internal pure returns (Currency) { return Currency.wrap(address(uint160(id))); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.20; import {Math} from "./Math.sol"; type FeePolicy is uint24; library FeePolicyLibrary { uint256 internal constant RATE_PRECISION = 10 ** 6; int256 internal constant MAX_FEE_RATE = 500000; int256 internal constant MIN_FEE_RATE = -500000; uint256 internal constant RATE_MASK = 0x7fffff; // 23 bits error InvalidFeePolicy(); function encode(bool usesQuote_, int24 rate_) internal pure returns (FeePolicy feePolicy) { if (rate_ > MAX_FEE_RATE || rate_ < MIN_FEE_RATE) { revert InvalidFeePolicy(); } uint256 mask = usesQuote_ ? 1 << 23 : 0; assembly { feePolicy := or(mask, add(and(rate_, 0xffffff), MAX_FEE_RATE)) } } function isValid(FeePolicy self) internal pure returns (bool) { int24 r = rate(self); return !(r > MAX_FEE_RATE || r < MIN_FEE_RATE); } function usesQuote(FeePolicy self) internal pure returns (bool f) { assembly { f := shr(23, self) } } function rate(FeePolicy self) internal pure returns (int24 r) { assembly { r := sub(and(self, RATE_MASK), MAX_FEE_RATE) } } function calculateFee(FeePolicy self, uint256 amount, bool reverseRounding) internal pure returns (int256 fee) { int24 r = rate(self); bool positive = r > 0; uint256 absRate; unchecked { absRate = uint256(uint24(positive ? r : -r)); } // @dev absFee must be less than type(int256).max uint256 absFee = Math.divide(amount * absRate, RATE_PRECISION, reverseRounding ? !positive : positive); fee = positive ? int256(absFee) : -int256(absFee); } function calculateOriginalAmount(FeePolicy self, uint256 amount, bool reverseFee) internal pure returns (uint256 originalAmount) { int24 r = rate(self); uint256 divider; assembly { if reverseFee { r := sub(0, r) } divider := add(RATE_PRECISION, r) } originalAmount = Math.divide(amount * RATE_PRECISION, divider, reverseFee); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; library Math { function divide(uint256 a, uint256 b, bool roundingUp) internal pure returns (uint256 ret) { // In the OrderBook contract code, b is never zero. assembly { ret := add(div(a, b), and(gt(mod(a, b), 0), roundingUp)) } } /// @dev Returns `ln(x)`, denominated in `WAD`. /// Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-ln function lnWad(int256 x) internal pure returns (int256 r) { /// @solidity memory-safe-assembly assembly { // We want to convert `x` from `10**18` fixed point to `2**96` fixed point. // We do this by multiplying by `2**96 / 10**18`. But since // `ln(x * C) = ln(x) + ln(C)`, we can simply do nothing here // and add `ln(2**96 / 10**18)` at the end. // Compute `k = log2(x) - 96`, `r = 159 - k = 255 - log2(x) = 255 ^ log2(x)`. r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // We place the check here for more optimal stack operations. if iszero(sgt(x, 0)) { mstore(0x00, 0x1615e638) // `LnWadUndefined()`. revert(0x1c, 0x04) } // forgefmt: disable-next-item r := xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), 0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff)) // Reduce range of x to (1, 2) * 2**96 // ln(2^k * x) = k * ln(2) + ln(x) x := shr(159, shl(r, x)) // Evaluate using a (8, 8)-term rational approximation. // `p` is made monic, we will multiply by a scale factor later. // forgefmt: disable-next-item let p := sub( // This heavily nested expression is to avoid stack-too-deep for via-ir. sar(96, mul(add(43456485725739037958740375743393, sar(96, mul(add(24828157081833163892658089445524, sar(96, mul(add(3273285459638523848632254066296, x), x))), x))), x)), 11111509109440967052023855526967) p := sub(sar(96, mul(p, x)), 45023709667254063763336534515857) p := sub(sar(96, mul(p, x)), 14706773417378608786704636184526) p := sub(mul(p, x), shl(96, 795164235651350426258249787498)) // We leave `p` in `2**192` basis so we don't need to scale it back up for the division. // `q` is monic by convention. let q := add(5573035233440673466300451813936, x) q := add(71694874799317883764090561454958, sar(96, mul(x, q))) q := add(283447036172924575727196451306956, sar(96, mul(x, q))) q := add(401686690394027663651624208769553, sar(96, mul(x, q))) q := add(204048457590392012362485061816622, sar(96, mul(x, q))) q := add(31853899698501571402653359427138, sar(96, mul(x, q))) q := add(909429971244387300277376558375, sar(96, mul(x, q))) // `p / q` is in the range `(0, 0.125) * 2**96`. // Finalization, we need to: // - Multiply by the scale factor `s = 5.549…`. // - Add `ln(2**96 / 10**18)`. // - Add `k * ln(2)`. // - Multiply by `10**18 / 2**96 = 5**18 >> 78`. // The q polynomial is known not to have zeros in the domain. // No scaling required because p is already `2**96` too large. p := sdiv(p, q) // Multiply by the scaling factor: `s * 5**18 * 2**96`, base is now `5**18 * 2**192`. p := mul(1677202110996718588342820967067443963516166, p) // Add `ln(2) * k * 5**18 * 2**192`. // forgefmt: disable-next-item p := add(mul(16597577552685614221487285958193947469193820559219878177908093499208371, sub(159, r)), p) // Base conversion: mul `2**96 / (5**18 * 2**192)`. r := sdiv(p, 302231454903657293676544000000000000000000) } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {Tick} from "./Tick.sol"; import {BookId} from "./BookId.sol"; type OrderId is uint256; library OrderIdLibrary { /** * @dev Encode the order id. * @param bookId The book id. * @param tick The tick. * @param index The index. * @return id The order id. */ function encode(BookId bookId, Tick tick, uint40 index) internal pure returns (OrderId id) { // @dev If we just use tick at the assembly code, the code will convert tick into bytes32. // e.g. When index == -2, the shifted value( shl(40, tick) ) will be // 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000 instead of 0xfffffffe0000000000 // Therefore, we have to safely cast tick into uint256 first. uint256 _tick = uint256(uint24(Tick.unwrap(tick))); assembly { id := add(index, add(shl(40, _tick), shl(64, bookId))) } } function decode(OrderId id) internal pure returns (BookId bookId, Tick tick, uint40 index) { assembly { bookId := shr(64, id) tick := and(shr(40, id), 0xffffff) index := and(id, 0xffffffffff) } } function getBookId(OrderId id) internal pure returns (BookId bookId) { assembly { bookId := shr(64, id) } } function getTick(OrderId id) internal pure returns (Tick tick) { assembly { tick := and(shr(40, id), 0xffffff) } } function getIndex(OrderId id) internal pure returns (uint40 index) { assembly { index := and(id, 0xffffffffff) } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.20; import {Math} from "./Math.sol"; type Tick is int24; library TickLibrary { using Math for *; using TickLibrary for Tick; error InvalidTick(); error InvalidPrice(); error TickOverflow(); int24 internal constant MAX_TICK = 2 ** 19 - 1; int24 internal constant MIN_TICK = -MAX_TICK; uint256 internal constant MIN_PRICE = 1350587; uint256 internal constant MAX_PRICE = 4647684107270898330752324302845848816923571339324334; uint256 private constant _R0 = 0xfff97272373d413259a46990; uint256 private constant _R1 = 0xfff2e50f5f656932ef12357c; uint256 private constant _R2 = 0xffe5caca7e10e4e61c3624ea; uint256 private constant _R3 = 0xffcb9843d60f6159c9db5883; uint256 private constant _R4 = 0xff973b41fa98c081472e6896; uint256 private constant _R5 = 0xff2ea16466c96a3843ec78b3; uint256 private constant _R6 = 0xfe5dee046a99a2a811c461f1; uint256 private constant _R7 = 0xfcbe86c7900a88aedcffc83b; uint256 private constant _R8 = 0xf987a7253ac413176f2b074c; uint256 private constant _R9 = 0xf3392b0822b70005940c7a39; uint256 private constant _R10 = 0xe7159475a2c29b7443b29c7f; uint256 private constant _R11 = 0xd097f3bdfd2022b8845ad8f7; uint256 private constant _R12 = 0xa9f746462d870fdf8a65dc1f; uint256 private constant _R13 = 0x70d869a156d2a1b890bb3df6; uint256 private constant _R14 = 0x31be135f97d08fd981231505; uint256 private constant _R15 = 0x9aa508b5b7a84e1c677de54; uint256 private constant _R16 = 0x5d6af8dedb81196699c329; uint256 private constant _R17 = 0x2216e584f5fa1ea92604; uint256 private constant _R18 = 0x48a170391f7dc42; uint256 private constant _R19 = 0x149b34; function validateTick(Tick tick) internal pure { if (Tick.unwrap(tick) > MAX_TICK || Tick.unwrap(tick) < MIN_TICK) revert InvalidTick(); } modifier validatePrice(uint256 price) { if (price > MAX_PRICE || price < MIN_PRICE) revert InvalidPrice(); _; } function fromPrice(uint256 price) internal pure validatePrice(price) returns (Tick) { unchecked { int24 tick = int24((int256(price).lnWad() * 42951820407860) / 2 ** 128); if (toPrice(Tick.wrap(tick)) > price) return Tick.wrap(tick - 1); return Tick.wrap(tick); } } function toPrice(Tick tick) internal pure returns (uint256 price) { validateTick(tick); int24 tickValue = Tick.unwrap(tick); uint256 absTick = uint24(tickValue < 0 ? -tickValue : tickValue); unchecked { if (absTick & 0x1 != 0) price = _R0; else price = 1 << 96; if (absTick & 0x2 != 0) price = (price * _R1) >> 96; if (absTick & 0x4 != 0) price = (price * _R2) >> 96; if (absTick & 0x8 != 0) price = (price * _R3) >> 96; if (absTick & 0x10 != 0) price = (price * _R4) >> 96; if (absTick & 0x20 != 0) price = (price * _R5) >> 96; if (absTick & 0x40 != 0) price = (price * _R6) >> 96; if (absTick & 0x80 != 0) price = (price * _R7) >> 96; if (absTick & 0x100 != 0) price = (price * _R8) >> 96; if (absTick & 0x200 != 0) price = (price * _R9) >> 96; if (absTick & 0x400 != 0) price = (price * _R10) >> 96; if (absTick & 0x800 != 0) price = (price * _R11) >> 96; if (absTick & 0x1000 != 0) price = (price * _R12) >> 96; if (absTick & 0x2000 != 0) price = (price * _R13) >> 96; if (absTick & 0x4000 != 0) price = (price * _R14) >> 96; if (absTick & 0x8000 != 0) price = (price * _R15) >> 96; if (absTick & 0x10000 != 0) price = (price * _R16) >> 96; if (absTick & 0x20000 != 0) price = (price * _R17) >> 96; if (absTick & 0x40000 != 0) price = (price * _R18) >> 96; } if (tickValue > 0) price = 0x1000000000000000000000000000000000000000000000000 / price; } function gt(Tick a, Tick b) internal pure returns (bool) { return Tick.unwrap(a) > Tick.unwrap(b); } function baseToQuote(Tick tick, uint256 base, bool roundingUp) internal pure returns (uint256) { return Math.divide((base * tick.toPrice()), 1 << 96, roundingUp); } function quoteToBase(Tick tick, uint256 quote, bool roundingUp) internal pure returns (uint256) { // @dev quote = unit(uint64) * unitSize(uint64) < 2^96 // We don't need to check overflow here return Math.divide(quote << 96, tick.toPrice(), roundingUp); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {IOracle} from "./IOracle.sol"; interface IDatastreamOracle is IOracle { error InvalidForwarder(); error InvalidReport(); error NotOperator(); error DifferentPrecision(); struct FeedData { address asset; /// @dev The feed index starts from 1 rather than 0. uint96 index; } struct Report { bytes32 feedId; // The feed ID the report has data for uint32 validFromTimestamp; // Earliest timestamp for which price is applicable uint32 observationsTimestamp; // Latest timestamp for which price is applicable uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (WETH/ETH) uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK uint32 expiresAt; // Latest timestamp where the report can be verified onchain int192 price; // DON consensus median price, carried to 8 decimal places int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation } event SetForwarder(address indexed forwarder); event SetFeed(address indexed asset, bytes32 feedId, uint256 index); event SetPrice(address indexed asset, uint256 price); event SetFallbackOracle(address indexed newFallbackOracle); event SetOperator(address indexed operator, bool status); event Request(address indexed requester, uint256 bitmap); /// @notice Checks if the specified account has operator privileges in this oracle system. /// @param account The address to check. /// @return True if `account` is an operator, false otherwise. function isOperator(address account) external view returns (bool); /// @notice Returns the address of the fallback oracle used when primary datastreams are invalid or unavailable. function fallbackOracle() external view returns (address); /// @notice Sets a new fallback oracle address. /// @param newFallbackOracle The address of the new fallback oracle contract. function setFallbackOracle(address newFallbackOracle) external; /// @notice Assigns a Chainlink/Datastream feed ID to a specific asset. /// @param feedId The unique feed ID representing data stream configuration on an off-chain system. /// @param asset The asset address for which this feed ID is being set. function setFeed(bytes32 feedId, address asset) external; /// @notice Sets the forwarder address, which may be used to route or handle oracle data externally. /// @param newForwarder The address of the forwarder contract. function setForwarder(address newForwarder) external; /// @notice Grants or revokes operator privileges for a given address. /// @param operator The address to be updated. /// @param status True to grant operator status, false to revoke. function setOperator(address operator, bool status) external; /// @notice Retrieves the list of all feed IDs currently registered in this oracle. /// @return An array of feed IDs (`bytes32`) managed by this contract. function getFeedIds() external view returns (bytes32[] memory); /// @notice Retrieves all feed data in bulk (feed IDs and corresponding asset info). /// @return feedIds An array of feed IDs. /// @return data An array of FeedData structs, each paired with the feedIds by index. function getAllFeedData() external view returns (bytes32[] memory feedIds, FeedData[] memory data); /// @notice Returns the address of the currently set forwarder contract. function forwarder() external view returns (address); /// @notice Returns the address of the fee token used for paying datastream fees. function feeToken() external view returns (address); /// @notice Returns the balance of the fee token held by this oracle contract. function feeBalance() external view returns (uint256); /// @notice Retrieves feed data (asset address, index) for a specific feed ID. /// @param feedId The ID of the feed to query. /// @return A FeedData struct containing asset info and feed index. function feedData(bytes32 feedId) external view returns (FeedData memory); /// @notice Sends a request with a specified bitmap to the oracle system. /// The bitmap might represent which feeds or data sets the caller is requesting. /// @param bitmap A bitwise representation of requested data sets or feed IDs. function request(uint256 bitmap) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {IBookManager} from "clober-dex/v2-core/interfaces/IBookManager.sol"; import {BookId} from "clober-dex/v2-core/libraries/BookId.sol"; import {OrderId} from "clober-dex/v2-core/libraries/OrderId.sol"; import {Currency} from "clober-dex/v2-core/libraries/Currency.sol"; import {IStrategy} from "./IStrategy.sol"; interface ILiquidityVault { struct Pool { BookId bookIdA; BookId bookIdB; IStrategy strategy; uint256 reserveA; uint256 reserveB; OrderId[] orderListA; OrderId[] orderListB; } error InvalidRate(); error NotSelf(); error InvalidHook(); error InvalidStrategy(); error InvalidBookPair(); error AlreadyOpened(); error InvalidLockAcquiredSender(); error InvalidLockCaller(); error LockFailure(); error InvalidAmount(); error InvalidValue(); error Slippage(); event Open(bytes32 indexed key, BookId indexed bookIdA, BookId indexed bookIdB, bytes32 salt, address strategy); event Mint(address indexed user, bytes32 indexed key, uint256 amountA, uint256 amountB, uint256 lpAmount); event Burn( address indexed user, bytes32 indexed key, uint256 lpAmount, uint256 amountA, uint256 amountB, uint256 feeA, uint256 feeB ); event Rebalance(bytes32 indexed key); event Claim(bytes32 indexed key, uint256 claimedAmountA, uint256 claimedAmountB); event Cancel(bytes32 indexed key, uint256 canceledAmountA, uint256 canceledAmountB); event Collect(Currency indexed currency, address indexed to, uint256 amount); struct Liquidity { uint256 reserve; uint256 claimable; uint256 cancelable; } /// @notice Retrieves the burn fee rate. /// @return The burn fee rate. function burnFeeRate() external view returns (uint256); /// @notice Returns the amount of pending fees for a given currency that can be collected /// @param currency The currency to check pending fees for /// @return The total amount of uncollected fees in the specified currency function fees(Currency currency) external view returns (uint256); /// @notice Retrieves the book pair for a specified book ID. /// @param bookId The book ID. /// @return The book pair. function bookPair(BookId bookId) external view returns (BookId); /// @notice Retrieves the pool for a specified key. /// @param key The key of the pool. /// @return The pool. function getPool(bytes32 key) external view returns (Pool memory); /// @notice Retrieves the book pairs for a specified key. /// @param key The key of the pool. /// @return bookIdA The book ID for the first book. /// @return bookIdB The book ID for the second book. function getBookPairs(bytes32 key) external view returns (BookId bookIdA, BookId bookIdB); /// @notice Retrieves the liquidity for a specified key. /// @param key The key of the pool. /// @return liquidityA The liquidity for the first token. /// @return liquidityB The liquidity for the second token. function getLiquidity(bytes32 key) external view returns (Liquidity memory liquidityA, Liquidity memory liquidityB); /// @notice Opens a new pool with the specified parameters. /// @param bookKeyA The book key for the first book. /// @param bookKeyB The book key for the second book. /// @param salt The salt value. /// @param strategy The address of the strategy. /// @return key The key of the opened pool. function open( IBookManager.BookKey calldata bookKeyA, IBookManager.BookKey calldata bookKeyB, bytes32 salt, address strategy ) external returns (bytes32 key); /// @notice Mints liquidity for the specified key. /// @param key The key of the pool. /// @param amountA The amount of the first token. /// @param amountB The amount of the second token. /// @param minLpAmount The minimum amount of liquidity tokens to mint. /// @return The amount of liquidity tokens minted. function mint(bytes32 key, uint256 amountA, uint256 amountB, uint256 minLpAmount) external payable returns (uint256); /// @notice Burns liquidity for the specified key. /// @param key The key of the pool. /// @param amount The amount of liquidity tokens to burn. /// @param minAmountA The amount of the first token to receive. /// @param minAmountB The minimum amount of the second token to receive. /// @return The amounts of the first and second tokens to receive. function burn(bytes32 key, uint256 amount, uint256 minAmountA, uint256 minAmountB) external returns (uint256, uint256); /// @notice Rebalances the pool for the specified key. /// @param key The key of the pool. function rebalance(bytes32 key) external; /// @notice Collects the pending fees for a given currency. /// @param currency The currency to collect fees for. /// @param to The address to send the collected fees to. /// @dev Only the owner can collect fees. function collect(Currency currency, address to) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; interface IOracle { /// @notice Retrieves the number of decimals used by the oracle. /// @return The number of decimals. function decimals() external view returns (uint8); /// @notice Retrieves the price of a specified asset. /// @param asset The address of the asset. /// @return The price of the asset. function getAssetPrice(address asset) external view returns (uint256); /// @notice Retrieves the prices of a list of specified assets. /// @param assets The list of asset addresses. /// @return The list of prices for the specified assets. function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {Tick} from "clober-dex/v2-core/libraries/Tick.sol"; import {IBookManager} from "clober-dex/v2-core/interfaces/IBookManager.sol"; import {IStrategy} from "./IStrategy.sol"; import {IOracle} from "./IOracle.sol"; import "./ILiquidityVault.sol"; interface ISimpleOracleStrategy is IStrategy { error InvalidPrice(); error InvalidAccess(); error InvalidOraclePrice(); error InvalidConfig(); error InvalidValue(); error ExceedsThreshold(); error NotOperator(); error Paused(); event SetOperator(address indexed operator, bool status); event UpdateConfig(bytes32 indexed key, Config config); event UpdatePosition(bytes32 indexed key, uint256 oraclePrice, Tick tickA, Tick tickB, uint256 rate); event Pause(bytes32 indexed key); event Unpause(bytes32 indexed key); struct Config { uint24 referenceThreshold; uint24 rebalanceThreshold; uint24 rateA; uint24 rateB; uint24 minRateA; uint24 minRateB; uint24 priceThresholdA; uint24 priceThresholdB; } struct Position { bool paused; uint176 oraclePrice; uint24 rate; Tick tickA; Tick tickB; } /// @notice Returns the reference IOracle contract used by this strategy. function referenceOracle() external view returns (IOracle); /// @notice Returns the IBookManager instance controlling the underlying orderbooks. function bookManager() external view returns (IBookManager); /// @notice Checks if a given address is granted operator privileges. /// @param operator The address to query. /// @return True if the address is an operator, otherwise false. function isOperator(address operator) external view returns (bool); /// @notice Fetches the configuration (Config struct) for a specified key. /// @param key A unique identifier for the position or pool. /// @return The current Config struct associated with the key. function getConfig(bytes32 key) external view returns (Config memory); /// @notice Retrieves the position (Position struct) for a specified key. /// @param key A unique identifier for the position or pool. /// @return A Position struct containing paused state, oracle price, rate, tickA, and tickB. function getPosition(bytes32 key) external view returns (Position memory); /// @notice Returns two amounts recorded in the last operation for a specified key. /// @param key A unique identifier for the position or pool. /// @return (uint256, uint256) representing the two amounts (likely token A / token B). function getLastAmount(bytes32 key) external view returns (uint256, uint256); /// @notice Checks if the oracle price for the specified key is valid according to the strategy's criteria. /// @param key A unique identifier for the position or pool. /// @return True if the oracle price is valid, otherwise false. function isOraclePriceValid(bytes32 key) external view returns (bool); /// @notice Queries whether the position for a specified key is paused. /// @param key A unique identifier for the position or pool. /// @return True if paused, false otherwise. function isPaused(bytes32 key) external view returns (bool); /// @notice Pauses the position corresponding to the given key, preventing further updates or orders. /// @param key A unique identifier for the position or pool. function pause(bytes32 key) external; /// @notice Unpauses the position for the given key, allowing normal strategy operations to resume. /// @param key A unique identifier for the position or pool. function unpause(bytes32 key) external; /// @notice Updates the position parameters based on a newly fetched oracle price and tick ranges. /// @param key A unique identifier for the position or pool. /// @param oraclePrice The new oracle price used to guide the strategy. /// @param tickA The updated tick parameters for side A of the orderbook. /// @param tickB The updated tick parameters for side B of the orderbook. /// @param rate The multiplier applied at the final step of order amount calculation. function updatePosition(bytes32 key, uint256 oraclePrice, Tick tickA, Tick tickB, uint24 rate) external; /// @notice Updates the configuration settings for the specified key. /// @param key A unique identifier for the position or pool. /// @param config The new configuration parameters (thresholds, rates, etc.). function setConfig(bytes32 key, Config memory config) external; /// @notice Assigns or revokes operator permissions for a given address. /// @param operator The address whose operator status is being updated. /// @param status True to grant operator privileges, false to revoke. function setOperator(address operator, bool status) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {BookId} from "clober-dex/v2-core/libraries/BookId.sol"; import {Tick} from "clober-dex/v2-core/libraries/Tick.sol"; interface IStrategy { struct Order { Tick tick; uint64 rawAmount; } /// @notice Retrieves the orders for a specified key. /// @param key The key of the pool. /// @return ordersA The orders for the first token. /// @return ordersB The orders for the second token. /// @dev Clears pool orders if an error occurs and retains current orders if the list is empty. function computeOrders(bytes32 key) external view returns (Order[] memory ordersA, Order[] memory ordersB); /// @notice Hook that is called after minting. /// @param sender The address of the sender. /// @param key The key of the pool. /// @param mintAmount The amount minted. /// @param lastTotalSupply The total supply before minting. function mintHook(address sender, bytes32 key, uint256 mintAmount, uint256 lastTotalSupply) external; /// @notice Hook that is called after burning. /// @param sender The address of the sender. /// @param key The key of the pool. /// @param burnAmount The amount burned. /// @param lastTotalSupply The total supply before burning. function burnHook(address sender, bytes32 key, uint256 burnAmount, uint256 lastTotalSupply) external; /// @notice Hook that is called after rebalancing. /// @param sender The address of the sender. /// @param key The key of the pool. /// @param liquidityA The liquidity orders for the first token. /// @param liquidityB The liquidity orders for the second token. /// @param amountA The amount of the first token. /// @param amountB The amount of the second token. function rebalanceHook( address sender, bytes32 key, Order[] memory liquidityA, Order[] memory liquidityB, uint256 amountA, uint256 amountB ) external; }
{ "evmVersion": "cancun", "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract ILiquidityVault","name":"liquidityVault_","type":"address"},{"internalType":"contract IDatastreamOracle","name":"datastreamOracle_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"ERC20TransferFailed","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NativeTransferFailed","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"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","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":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"datastreamOracle","outputs":[{"internalType":"contract IDatastreamOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"uint256","name":"requestFeeAmount_","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidityVault","outputs":[{"internalType":"contract ILiquidityVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestFeeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bitmap","type":"uint256"}],"name":"requestOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestOraclePublic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestFeeAmount_","type":"uint256"}],"name":"setRequestFeeAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"uint256","name":"oraclePrice","type":"uint256"},{"internalType":"Tick","name":"tickA","type":"int24"},{"internalType":"Tick","name":"tickB","type":"int24"},{"internalType":"uint24","name":"rate","type":"uint24"}],"name":"updatePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"Currency","name":"currency","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e060405230608052348015610013575f80fd5b506040516117cf3803806117cf833981016040819052610032916100f7565b338061005757604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61006081610078565b506001600160a01b0391821660a0521660c05261012f565b600180546001600160a01b031916905561009181610094565b50565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114610091575f80fd5b5f8060408385031215610108575f80fd5b8251610113816100e3565b6020840151909250610124816100e3565b809150509250929050565b60805160a05160c0516116376101985f395f818161014e0152818161039c015281816104c501526109e701525f81816101d3015281816105fe015281816107fe01528181610a3c0152610b2101525f8181610be201528181610c0b0152610d8901526116375ff3fe608060405260043610610123575f3560e01c8063a0f15331116100a1578063d9caed1211610071578063eb07646111610057578063eb0764611461033c578063ed56531a1461035b578063f2fde38b1461037a575f80fd5b8063d9caed1214610300578063e30c39781461031f575f80fd5b8063a0f1533114610258578063ad1b358d14610277578063ad3cb1cc1461028c578063cd6dc687146102e1575f80fd5b8063708666ad116100f657806379ba5097116100dc57806379ba5097146102095780638da5cb5b1461021d5780638f3f068f14610239575f80fd5b8063708666ad146101c2578063715018a6146101f5575f80fd5b806327620d831461012757806328a6cf3d1461013d5780634f1ef2861461018d57806352d1902d146101a0575b5f80fd5b348015610132575f80fd5b5061013b610399565b005b348015610148575f80fd5b506101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61013b61019b366004611234565b610528565b3480156101ab575f80fd5b506101b4610547565b604051908152602001610184565b3480156101cd575f80fd5b506101707f000000000000000000000000000000000000000000000000000000000000000081565b348015610200575f80fd5b5061013b610575565b348015610214575f80fd5b5061013b610588565b348015610228575f80fd5b505f546001600160a01b0316610170565b348015610244575f80fd5b5061013b6102533660046112d6565b6105d1565b348015610263575f80fd5b5061013b610272366004611303565b6105de565b348015610282575f80fd5b506101b460025481565b348015610297575f80fd5b506102d46040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101849190611361565b3480156102ec575f80fd5b5061013b6102fb366004611396565b610867565b34801561030b575f80fd5b5061013b61031a3660046113c0565b6109a8565b34801561032a575f80fd5b506001546001600160a01b0316610170565b348015610347575f80fd5b5061013b6103563660046112d6565b6109c9565b348015610366575f80fd5b5061013b6103753660046112d6565b610a1e565b348015610385575f80fd5b5061013b6103943660046113fe565b610b5a565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663647846a56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061041a9190611419565b6002546040517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101919091529091506001600160a01b038216906323b872dd906064016020604051808303815f875af115801561048a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ae9190611434565b5060405163d845a4b360e01b81525f1960048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d845a4b3906024015b5f604051808303815f87803b15801561050f575f80fd5b505af1158015610521573d5f803e3d5ffd5b5050505050565b610530610bd7565b61053982610c8e565b6105438282610c96565b5050565b5f610550610d7e565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b61057d610dc7565b6105865f610df3565b565b60015433906001600160a01b031681146105c55760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b6105ce81610df3565b50565b6105d9610dc7565b600255565b6105e6610dc7565b60405163f6c0092760e01b8152600481018690525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f6c00927906024015f60405180830381865afa15801561064a573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106719190810190611502565b604001519050806001600160a01b031663241b71bb876040518263ffffffff1660e01b81526004016106a591815260200190565b602060405180830381865afa1580156106c0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106e49190611434565b15610758576040517f2f4dae9f000000000000000000000000000000000000000000000000000000008152600481018790526001600160a01b03821690632f4dae9f906024015f604051808303815f87803b158015610741575f80fd5b505af1158015610753573d5f803e3d5ffd5b505050505b6040517fa0f153310000000000000000000000000000000000000000000000000000000081526004810187905260248101869052600285810b604483015284900b606482015262ffffff831660848201526001600160a01b0382169063a0f153319060a4015f604051808303815f87803b1580156107d4575f80fd5b505af11580156107e6573d5f803e3d5ffd5b505060405163036045d960e31b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169250631b022ec891506024015f604051808303815f87803b158015610849575f80fd5b505af115801561085b573d5f803e3d5ffd5b50505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f811580156108b15750825b90505f8267ffffffffffffffff1660011480156108cd5750303b155b9050811580156108db575080155b15610912576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561094657845468ff00000000000000001916680100000000000000001785555b61094f87610df3565b6002869055831561099f57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6109b0610dc7565b6109c46001600160a01b0384168383610e19565b505050565b6109d1610dc7565b60405163d845a4b360e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d845a4b3906024016104f8565b610a26610dc7565b60405163f6c0092760e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f6c00927906024015f60405180830381865afa158015610a88573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610aaf9190810190611502565b604001516001600160a01b031663ed56531a826040518263ffffffff1660e01b8152600401610ae091815260200190565b5f604051808303815f87803b158015610af7575f80fd5b505af1158015610b09573d5f803e3d5ffd5b505060405163036045d960e31b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169250631b022ec891506024016104f8565b610b62610dc7565b600180546001600160a01b03831673ffffffffffffffffffffffffffffffffffffffff199091168117909155610b9f5f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610c7057507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c647f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156105865760405163703e46dd60e11b815260040160405180910390fd5b6105ce610dc7565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610cf0575060408051601f3d908101601f19168201909252610ced918101906115d4565b60015b610d1857604051634c9c8ce360e01b81526001600160a01b03831660048201526024016105bc565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610d74576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016105bc565b6109c48383610f01565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105865760405163703e46dd60e11b815260040160405180910390fd5b5f546001600160a01b031633146105865760405163118cdaa760e01b81523360048201526024016105bc565b6001805473ffffffffffffffffffffffffffffffffffffffff191690556105ce81610f56565b5f6001600160a01b038416610e6e575f805f8085875af1905080610e69576040517ff4b3b1bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610efb565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015282602482015260205f6044835f895af13d15601f3d1160015f511416171691505080610efb576040517ff27f64e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b610f0a82610fb2565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115610f4e576109c48282611035565b6105436110a7565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b806001600160a01b03163b5f03610fe757604051634c9c8ce360e01b81526001600160a01b03821660048201526024016105bc565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b03168460405161105191906115eb565b5f60405180830381855af49150503d805f8114611089576040519150601f19603f3d011682016040523d82523d5f602084013e61108e565b606091505b509150915061109e8583836110df565b95945050505050565b3415610586576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060826110f4576110ef82611157565b611150565b815115801561110b57506001600160a01b0384163b155b1561114d576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016105bc565b50805b9392505050565b8051156111675780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03811681146105ce575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160e0810167ffffffffffffffff811182821017156111fd576111fd6111ad565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561122c5761122c6111ad565b604052919050565b5f8060408385031215611245575f80fd5b823561125081611199565b915060208381013567ffffffffffffffff8082111561126d575f80fd5b818601915086601f830112611280575f80fd5b813581811115611292576112926111ad565b6112a4601f8201601f19168501611203565b915080825287848285010111156112b9575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f602082840312156112e6575f80fd5b5035919050565b8035600281900b81146112fe575f80fd5b919050565b5f805f805f60a08688031215611317575f80fd5b853594506020860135935061132e604087016112ed565b925061133c606087016112ed565b9150608086013562ffffff81168114611353575f80fd5b809150509295509295909350565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f80604083850312156113a7575f80fd5b82356113b281611199565b946020939093013593505050565b5f805f606084860312156113d2575f80fd5b83356113dd81611199565b925060208401356113ed81611199565b929592945050506040919091013590565b5f6020828403121561140e575f80fd5b813561115081611199565b5f60208284031215611429575f80fd5b815161115081611199565b5f60208284031215611444575f80fd5b81518015158114611150575f80fd5b805177ffffffffffffffffffffffffffffffffffffffffffffffff811681146112fe575f80fd5b80516112fe81611199565b5f82601f830112611494575f80fd5b8151602067ffffffffffffffff8211156114b0576114b06111ad565b8160051b6114bf828201611203565b92835284810182019282810190878511156114d8575f80fd5b83870192505b848310156114f7578251825291830191908301906114de565b979650505050505050565b5f60208284031215611512575f80fd5b815167ffffffffffffffff80821115611529575f80fd5b9083019060e0828603121561153c575f80fd5b6115446111da565b61154d83611453565b815261155b60208401611453565b602082015261156c6040840161147a565b6040820152606083015160608201526080830151608082015260a083015182811115611596575f80fd5b6115a287828601611485565b60a08301525060c0830151828111156115b9575f80fd5b6115c587828601611485565b60c08301525095945050505050565b5f602082840312156115e4575f80fd5b5051919050565b5f82518060208501845e5f92019182525091905056fea26469706673582212200fd7cb4020bd540d10c78f4403ac3a8c97fcb1123044332705641cb7a1bf34ac64736f6c6343000819003300000000000000000000000046107ec44112675689053b96aea2127fd952bd470000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405260043610610123575f3560e01c8063a0f15331116100a1578063d9caed1211610071578063eb07646111610057578063eb0764611461033c578063ed56531a1461035b578063f2fde38b1461037a575f80fd5b8063d9caed1214610300578063e30c39781461031f575f80fd5b8063a0f1533114610258578063ad1b358d14610277578063ad3cb1cc1461028c578063cd6dc687146102e1575f80fd5b8063708666ad116100f657806379ba5097116100dc57806379ba5097146102095780638da5cb5b1461021d5780638f3f068f14610239575f80fd5b8063708666ad146101c2578063715018a6146101f5575f80fd5b806327620d831461012757806328a6cf3d1461013d5780634f1ef2861461018d57806352d1902d146101a0575b5f80fd5b348015610132575f80fd5b5061013b610399565b005b348015610148575f80fd5b506101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61013b61019b366004611234565b610528565b3480156101ab575f80fd5b506101b4610547565b604051908152602001610184565b3480156101cd575f80fd5b506101707f00000000000000000000000046107ec44112675689053b96aea2127fd952bd4781565b348015610200575f80fd5b5061013b610575565b348015610214575f80fd5b5061013b610588565b348015610228575f80fd5b505f546001600160a01b0316610170565b348015610244575f80fd5b5061013b6102533660046112d6565b6105d1565b348015610263575f80fd5b5061013b610272366004611303565b6105de565b348015610282575f80fd5b506101b460025481565b348015610297575f80fd5b506102d46040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101849190611361565b3480156102ec575f80fd5b5061013b6102fb366004611396565b610867565b34801561030b575f80fd5b5061013b61031a3660046113c0565b6109a8565b34801561032a575f80fd5b506001546001600160a01b0316610170565b348015610347575f80fd5b5061013b6103563660046112d6565b6109c9565b348015610366575f80fd5b5061013b6103753660046112d6565b610a1e565b348015610385575f80fd5b5061013b6103943660046113fe565b610b5a565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663647846a56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061041a9190611419565b6002546040517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101919091529091506001600160a01b038216906323b872dd906064016020604051808303815f875af115801561048a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ae9190611434565b5060405163d845a4b360e01b81525f1960048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d845a4b3906024015b5f604051808303815f87803b15801561050f575f80fd5b505af1158015610521573d5f803e3d5ffd5b5050505050565b610530610bd7565b61053982610c8e565b6105438282610c96565b5050565b5f610550610d7e565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b61057d610dc7565b6105865f610df3565b565b60015433906001600160a01b031681146105c55760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b6105ce81610df3565b50565b6105d9610dc7565b600255565b6105e6610dc7565b60405163f6c0092760e01b8152600481018690525f907f00000000000000000000000046107ec44112675689053b96aea2127fd952bd476001600160a01b03169063f6c00927906024015f60405180830381865afa15801561064a573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106719190810190611502565b604001519050806001600160a01b031663241b71bb876040518263ffffffff1660e01b81526004016106a591815260200190565b602060405180830381865afa1580156106c0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106e49190611434565b15610758576040517f2f4dae9f000000000000000000000000000000000000000000000000000000008152600481018790526001600160a01b03821690632f4dae9f906024015f604051808303815f87803b158015610741575f80fd5b505af1158015610753573d5f803e3d5ffd5b505050505b6040517fa0f153310000000000000000000000000000000000000000000000000000000081526004810187905260248101869052600285810b604483015284900b606482015262ffffff831660848201526001600160a01b0382169063a0f153319060a4015f604051808303815f87803b1580156107d4575f80fd5b505af11580156107e6573d5f803e3d5ffd5b505060405163036045d960e31b8152600481018990527f00000000000000000000000046107ec44112675689053b96aea2127fd952bd476001600160a01b03169250631b022ec891506024015f604051808303815f87803b158015610849575f80fd5b505af115801561085b573d5f803e3d5ffd5b50505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f811580156108b15750825b90505f8267ffffffffffffffff1660011480156108cd5750303b155b9050811580156108db575080155b15610912576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561094657845468ff00000000000000001916680100000000000000001785555b61094f87610df3565b6002869055831561099f57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6109b0610dc7565b6109c46001600160a01b0384168383610e19565b505050565b6109d1610dc7565b60405163d845a4b360e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d845a4b3906024016104f8565b610a26610dc7565b60405163f6c0092760e01b8152600481018290527f00000000000000000000000046107ec44112675689053b96aea2127fd952bd476001600160a01b03169063f6c00927906024015f60405180830381865afa158015610a88573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610aaf9190810190611502565b604001516001600160a01b031663ed56531a826040518263ffffffff1660e01b8152600401610ae091815260200190565b5f604051808303815f87803b158015610af7575f80fd5b505af1158015610b09573d5f803e3d5ffd5b505060405163036045d960e31b8152600481018490527f00000000000000000000000046107ec44112675689053b96aea2127fd952bd476001600160a01b03169250631b022ec891506024016104f8565b610b62610dc7565b600180546001600160a01b03831673ffffffffffffffffffffffffffffffffffffffff199091168117909155610b9f5f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b306001600160a01b037f000000000000000000000000dab095a21df1fba2c9255c2deb6949caf128f404161480610c7057507f000000000000000000000000dab095a21df1fba2c9255c2deb6949caf128f4046001600160a01b0316610c647f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156105865760405163703e46dd60e11b815260040160405180910390fd5b6105ce610dc7565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610cf0575060408051601f3d908101601f19168201909252610ced918101906115d4565b60015b610d1857604051634c9c8ce360e01b81526001600160a01b03831660048201526024016105bc565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610d74576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016105bc565b6109c48383610f01565b306001600160a01b037f000000000000000000000000dab095a21df1fba2c9255c2deb6949caf128f40416146105865760405163703e46dd60e11b815260040160405180910390fd5b5f546001600160a01b031633146105865760405163118cdaa760e01b81523360048201526024016105bc565b6001805473ffffffffffffffffffffffffffffffffffffffff191690556105ce81610f56565b5f6001600160a01b038416610e6e575f805f8085875af1905080610e69576040517ff4b3b1bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610efb565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015282602482015260205f6044835f895af13d15601f3d1160015f511416171691505080610efb576040517ff27f64e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b610f0a82610fb2565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115610f4e576109c48282611035565b6105436110a7565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b806001600160a01b03163b5f03610fe757604051634c9c8ce360e01b81526001600160a01b03821660048201526024016105bc565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b03168460405161105191906115eb565b5f60405180830381855af49150503d805f8114611089576040519150601f19603f3d011682016040523d82523d5f602084013e61108e565b606091505b509150915061109e8583836110df565b95945050505050565b3415610586576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060826110f4576110ef82611157565b611150565b815115801561110b57506001600160a01b0384163b155b1561114d576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016105bc565b50805b9392505050565b8051156111675780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03811681146105ce575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160e0810167ffffffffffffffff811182821017156111fd576111fd6111ad565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561122c5761122c6111ad565b604052919050565b5f8060408385031215611245575f80fd5b823561125081611199565b915060208381013567ffffffffffffffff8082111561126d575f80fd5b818601915086601f830112611280575f80fd5b813581811115611292576112926111ad565b6112a4601f8201601f19168501611203565b915080825287848285010111156112b9575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f602082840312156112e6575f80fd5b5035919050565b8035600281900b81146112fe575f80fd5b919050565b5f805f805f60a08688031215611317575f80fd5b853594506020860135935061132e604087016112ed565b925061133c606087016112ed565b9150608086013562ffffff81168114611353575f80fd5b809150509295509295909350565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f80604083850312156113a7575f80fd5b82356113b281611199565b946020939093013593505050565b5f805f606084860312156113d2575f80fd5b83356113dd81611199565b925060208401356113ed81611199565b929592945050506040919091013590565b5f6020828403121561140e575f80fd5b813561115081611199565b5f60208284031215611429575f80fd5b815161115081611199565b5f60208284031215611444575f80fd5b81518015158114611150575f80fd5b805177ffffffffffffffffffffffffffffffffffffffffffffffff811681146112fe575f80fd5b80516112fe81611199565b5f82601f830112611494575f80fd5b8151602067ffffffffffffffff8211156114b0576114b06111ad565b8160051b6114bf828201611203565b92835284810182019282810190878511156114d8575f80fd5b83870192505b848310156114f7578251825291830191908301906114de565b979650505050505050565b5f60208284031215611512575f80fd5b815167ffffffffffffffff80821115611529575f80fd5b9083019060e0828603121561153c575f80fd5b6115446111da565b61154d83611453565b815261155b60208401611453565b602082015261156c6040840161147a565b6040820152606083015160608201526080830151608082015260a083015182811115611596575f80fd5b6115a287828601611485565b60a08301525060c0830151828111156115b9575f80fd5b6115c587828601611485565b60c08301525095945050505050565b5f602082840312156115e4575f80fd5b5051919050565b5f82518060208501845e5f92019182525091905056fea26469706673582212200fd7cb4020bd540d10c78f4403ac3a8c97fcb1123044332705641cb7a1bf34ac64736f6c63430008190033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000046107ec44112675689053b96aea2127fd952bd470000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : liquidityVault_ (address): 0x46107Ec44112675689053b96aea2127fD952bd47
Arg [1] : datastreamOracle_ (address): 0x0000000000000000000000000000000000000000
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000046107ec44112675689053b96aea2127fd952bd47
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.