Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21910495 | 2 days ago | 12.4591347 ETH | ||||
21910495 | 2 days ago | 12.4591347 ETH | ||||
21903519 | 3 days ago | 201.91939266 ETH | ||||
21903519 | 3 days ago | 201.91939266 ETH | ||||
21899924 | 3 days ago | 53.79526661 ETH | ||||
21899924 | 3 days ago | 53.79526661 ETH | ||||
21896369 | 4 days ago | 5.42882475 ETH | ||||
21896369 | 4 days ago | 5.42882475 ETH | ||||
21834514 | 12 days ago | 32.73496941 ETH | ||||
21834514 | 12 days ago | 32.73496941 ETH | ||||
21825123 | 14 days ago | 17.00654488 ETH | ||||
21825123 | 14 days ago | 17.00654488 ETH | ||||
21793428 | 18 days ago | 5.92543715 ETH | ||||
21793428 | 18 days ago | 5.92543715 ETH | ||||
21783740 | 19 days ago | 0.13351 ETH | ||||
21783740 | 19 days ago | 0.13351 ETH | ||||
21783049 | 20 days ago | 8.23081321 ETH | ||||
21783049 | 20 days ago | 8.23081321 ETH | ||||
21780899 | 20 days ago | 29.62083814 ETH | ||||
21780899 | 20 days ago | 29.62083814 ETH | ||||
21776851 | 20 days ago | 494.19800296 ETH | ||||
21776851 | 20 days ago | 494.19800296 ETH | ||||
21738034 | 26 days ago | 0.0070272 ETH | ||||
21738034 | 26 days ago | 0.0070272 ETH | ||||
21715799 | 29 days ago | 5.17330517 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
EthOsTokenVaultEscrow
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 200 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {Address} from '@openzeppelin/contracts/utils/Address.sol'; import {ReentrancyGuard} from '@openzeppelin/contracts/utils/ReentrancyGuard.sol'; import {Errors} from '../libraries/Errors.sol'; import {OsTokenVaultEscrow} from './OsTokenVaultEscrow.sol'; /** * @title EthOsTokenVaultEscrow * @author StakeWise * @notice Used for initiating assets exits from the vault without burning osToken on Ethereum */ contract EthOsTokenVaultEscrow is ReentrancyGuard, OsTokenVaultEscrow { /** * @notice Event emitted on assets received by the escrow * @param sender The address of the sender * @param value The amount of assets received */ event AssetsReceived(address indexed sender, uint256 value); /** * @dev Constructor * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param initialOwner The address of the contract owner * @param _authenticator The address of the OsTokenVaultEscrowAuth contract * @param _liqThresholdPercent The liquidation threshold percent * @param _liqBonusPercent The liquidation bonus percent */ constructor( address osTokenVaultController, address osTokenConfig, address initialOwner, address _authenticator, uint64 _liqThresholdPercent, uint256 _liqBonusPercent ) ReentrancyGuard() OsTokenVaultEscrow( osTokenVaultController, osTokenConfig, initialOwner, _authenticator, _liqThresholdPercent, _liqBonusPercent ) {} /** * @dev Function for receiving assets from the vault */ receive() external payable { emit AssetsReceived(msg.sender, msg.value); } /// @inheritdoc OsTokenVaultEscrow function _transferAssets(address receiver, uint256 assets) internal override nonReentrant { return Address.sendValue(payable(receiver), assets); } }
// 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.0.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. * * 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. */ 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.0.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.20; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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 AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 * {FailedInnerCall} 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 AddressInsufficientBalance(address(this)); } (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 {FailedInnerCall}) 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 {FailedInnerCall} 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 {FailedInnerCall}. */ 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// 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.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.22; import '../interfaces/IMulticall.sol'; /** * @title Multicall * @author Uniswap * @notice Adopted from https://github.com/Uniswap/v3-periphery/blob/1d69caf0d6c8cfeae9acd1f34ead30018d6e6400/contracts/base/Multicall.sol * @notice Enables calling multiple methods in a single call to the contract */ abstract contract Multicall is IMulticall { /// @inheritdoc IMulticall function multicall(bytes[] calldata data) external override returns (bytes[] memory results) { uint256 dataLength = data.length; results = new bytes[](dataLength); for (uint256 i = 0; i < dataLength; i++) { (bool success, bytes memory result) = address(this).delegatecall(data[i]); if (!success) { // Next 5 lines from https://ethereum.stackexchange.com/a/83577 if (result.length < 68) revert(); assembly { result := add(result, 0x04) } revert(abi.decode(result, (string))); } results[i] = result; } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IERC5267} from '@openzeppelin/contracts/interfaces/IERC5267.sol'; /** * @title IKeeperOracles * @author StakeWise * @notice Defines the interface for the KeeperOracles contract */ interface IKeeperOracles is IERC5267 { /** * @notice Event emitted on the oracle addition * @param oracle The address of the added oracle */ event OracleAdded(address indexed oracle); /** * @notice Event emitted on the oracle removal * @param oracle The address of the removed oracle */ event OracleRemoved(address indexed oracle); /** * @notice Event emitted on oracles config update * @param configIpfsHash The IPFS hash of the new config */ event ConfigUpdated(string configIpfsHash); /** * @notice Function for verifying whether oracle is registered or not * @param oracle The address of the oracle to check * @return `true` for the registered oracle, `false` otherwise */ function isOracle(address oracle) external view returns (bool); /** * @notice Total Oracles * @return The total number of oracles registered */ function totalOracles() external view returns (uint256); /** * @notice Function for adding oracle to the set * @param oracle The address of the oracle to add */ function addOracle(address oracle) external; /** * @notice Function for removing oracle from the set * @param oracle The address of the oracle to remove */ function removeOracle(address oracle) external; /** * @notice Function for updating the config IPFS hash * @param configIpfsHash The new config IPFS hash */ function updateConfig(string calldata configIpfsHash) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperOracles} from './IKeeperOracles.sol'; /** * @title IKeeperRewards * @author StakeWise * @notice Defines the interface for the Keeper contract rewards */ interface IKeeperRewards is IKeeperOracles { /** * @notice Event emitted on rewards update * @param caller The address of the function caller * @param rewardsRoot The new rewards merkle tree root * @param avgRewardPerSecond The new average reward per second * @param updateTimestamp The update timestamp used for rewards calculation * @param nonce The nonce used for verifying signatures * @param rewardsIpfsHash The new rewards IPFS hash */ event RewardsUpdated( address indexed caller, bytes32 indexed rewardsRoot, uint256 avgRewardPerSecond, uint64 updateTimestamp, uint64 nonce, string rewardsIpfsHash ); /** * @notice Event emitted on Vault harvest * @param vault The address of the Vault * @param rewardsRoot The rewards merkle tree root * @param totalAssetsDelta The Vault total assets delta since last sync. Can be negative in case of penalty/slashing. * @param unlockedMevDelta The Vault execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. */ event Harvested( address indexed vault, bytes32 indexed rewardsRoot, int256 totalAssetsDelta, uint256 unlockedMevDelta ); /** * @notice Event emitted on rewards min oracles number update * @param oracles The new minimum number of oracles required to update rewards */ event RewardsMinOraclesUpdated(uint256 oracles); /** * @notice A struct containing the last synced Vault's cumulative reward * @param assets The Vault cumulative reward earned since the start. Can be negative in case of penalty/slashing. * @param nonce The nonce of the last sync */ struct Reward { int192 assets; uint64 nonce; } /** * @notice A struct containing the last unlocked Vault's cumulative execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. * @param assets The shared MEV Vault's cumulative execution reward that can be withdrawn * @param nonce The nonce of the last sync */ struct UnlockedMevReward { uint192 assets; uint64 nonce; } /** * @notice A struct containing parameters for rewards update * @param rewardsRoot The new rewards merkle root * @param avgRewardPerSecond The new average reward per second * @param updateTimestamp The update timestamp used for rewards calculation * @param rewardsIpfsHash The new IPFS hash with all the Vaults' rewards for the new root * @param signatures The concatenation of the Oracles' signatures */ struct RewardsUpdateParams { bytes32 rewardsRoot; uint256 avgRewardPerSecond; uint64 updateTimestamp; string rewardsIpfsHash; bytes signatures; } /** * @notice A struct containing parameters for harvesting rewards. Can only be called by Vault. * @param rewardsRoot The rewards merkle root * @param reward The Vault cumulative reward earned since the start. Can be negative in case of penalty/slashing. * @param unlockedMevReward The Vault cumulative execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. * @param proof The proof to verify that Vault's reward is correct */ struct HarvestParams { bytes32 rewardsRoot; int160 reward; uint160 unlockedMevReward; bytes32[] proof; } /** * @notice Previous Rewards Root * @return The previous merkle tree root of the rewards accumulated by the Vaults */ function prevRewardsRoot() external view returns (bytes32); /** * @notice Rewards Root * @return The latest merkle tree root of the rewards accumulated by the Vaults */ function rewardsRoot() external view returns (bytes32); /** * @notice Rewards Nonce * @return The nonce used for updating rewards merkle tree root */ function rewardsNonce() external view returns (uint64); /** * @notice The last rewards update * @return The timestamp of the last rewards update */ function lastRewardsTimestamp() external view returns (uint64); /** * @notice The minimum number of oracles required to update rewards * @return The minimum number of oracles */ function rewardsMinOracles() external view returns (uint256); /** * @notice The rewards delay * @return The delay in seconds between rewards updates */ function rewardsDelay() external view returns (uint256); /** * @notice Get last synced Vault cumulative reward * @param vault The address of the Vault * @return assets The last synced reward assets * @return nonce The last synced reward nonce */ function rewards(address vault) external view returns (int192 assets, uint64 nonce); /** * @notice Get last unlocked shared MEV Vault cumulative reward * @param vault The address of the Vault * @return assets The last synced reward assets * @return nonce The last synced reward nonce */ function unlockedMevRewards(address vault) external view returns (uint192 assets, uint64 nonce); /** * @notice Checks whether Vault must be harvested * @param vault The address of the Vault * @return `true` if the Vault requires harvesting, `false` otherwise */ function isHarvestRequired(address vault) external view returns (bool); /** * @notice Checks whether the Vault can be harvested * @param vault The address of the Vault * @return `true` if Vault can be harvested, `false` otherwise */ function canHarvest(address vault) external view returns (bool); /** * @notice Checks whether rewards can be updated * @return `true` if rewards can be updated, `false` otherwise */ function canUpdateRewards() external view returns (bool); /** * @notice Checks whether the Vault has registered validators * @param vault The address of the Vault * @return `true` if Vault is collateralized, `false` otherwise */ function isCollateralized(address vault) external view returns (bool); /** * @notice Update rewards data * @param params The struct containing rewards update parameters */ function updateRewards(RewardsUpdateParams calldata params) external; /** * @notice Harvest rewards. Can be called only by Vault. * @param params The struct containing rewards harvesting parameters * @return totalAssetsDelta The total reward/penalty accumulated by the Vault since the last sync * @return unlockedMevDelta The Vault execution reward that can be withdrawn from shared MEV escrow. Only used by shared MEV Vaults. * @return harvested `true` when the rewards were harvested, `false` otherwise */ function harvest( HarvestParams calldata params ) external returns (int256 totalAssetsDelta, uint256 unlockedMevDelta, bool harvested); /** * @notice Set min number of oracles for confirming rewards update. Can only be called by the owner. * @param _rewardsMinOracles The new min number of oracles for confirming rewards update */ function setRewardsMinOracles(uint256 _rewardsMinOracles) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.22; /** * @title Multicall * @author Uniswap * @notice Adopted from https://github.com/Uniswap/v3-periphery/blob/1d69caf0d6c8cfeae9acd1f34ead30018d6e6400/contracts/base/Multicall.sol * @notice Enables calling multiple methods in a single call to the contract */ interface IMulticall { /** * @notice Call multiple functions in the current contract and return the data from all of them if they all succeed * @param data The encoded function data for each of the calls to make to this contract * @return results The results from each of the calls passed in via data */ function multicall(bytes[] calldata data) external returns (bytes[] memory results); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IOsTokenConfig * @author StakeWise * @notice Defines the interface for the OsTokenConfig contract */ interface IOsTokenConfig { /** * @notice Emitted when OsToken minting and liquidating configuration values are updated * @param vault The address of the vault to update the config for. Will be zero address if it is a default config. * @param liqBonusPercent The new liquidation bonus percent value * @param liqThresholdPercent The new liquidation threshold percent value * @param ltvPercent The new loan-to-value (LTV) percent value */ event OsTokenConfigUpdated( address vault, uint128 liqBonusPercent, uint64 liqThresholdPercent, uint64 ltvPercent ); /** * @notice Emitted when the OsToken redeemer address is updated * @param newRedeemer The address of the new redeemer */ event RedeemerUpdated(address newRedeemer); /** * @notice The OsToken minting and liquidating configuration values * @param liqThresholdPercent The liquidation threshold percent used to calculate health factor for OsToken position * @param liqBonusPercent The minimal bonus percent that liquidator earns on OsToken position liquidation * @param ltvPercent The percent used to calculate how much user can mint OsToken shares */ struct Config { uint128 liqBonusPercent; uint64 liqThresholdPercent; uint64 ltvPercent; } /** * @notice The address of the OsToken redeemer * @return The address of the redeemer */ function redeemer() external view returns (address); /** * @notice Returns the OsToken minting and liquidating configuration values for the vault * @param vault The address of the vault to get the config for * @return config The OsToken config for the vault */ function getConfig(address vault) external view returns (Config memory config); /** * @notice Sets the OsToken redeemer address. Can only be called by the owner. * @param newRedeemer The address of the new redeemer */ function setRedeemer(address newRedeemer) external; /** * @notice Updates the OsToken minting and liquidating configuration values. Can only be called by the owner. * @param vault The address of the vault. Set to zero address to update the default config. * @param config The new OsToken configuration */ function updateConfig(address vault, Config memory config) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IOsTokenVaultController * @author StakeWise * @notice Defines the interface for the OsTokenVaultController contract */ interface IOsTokenVaultController { /** * @notice Event emitted on minting shares * @param vault The address of the Vault * @param receiver The address that received the shares * @param assets The number of assets collateralized * @param shares The number of tokens the owner received */ event Mint(address indexed vault, address indexed receiver, uint256 assets, uint256 shares); /** * @notice Event emitted on burning shares * @param vault The address of the Vault * @param owner The address that owns the shares * @param assets The total number of assets withdrawn * @param shares The total number of shares burned */ event Burn(address indexed vault, address indexed owner, uint256 assets, uint256 shares); /** * @notice Event emitted on state update * @param profitAccrued The profit accrued since the last update * @param treasuryShares The number of shares minted for the treasury * @param treasuryAssets The number of assets minted for the treasury */ event StateUpdated(uint256 profitAccrued, uint256 treasuryShares, uint256 treasuryAssets); /** * @notice Event emitted on capacity update * @param capacity The amount after which the OsToken stops accepting deposits */ event CapacityUpdated(uint256 capacity); /** * @notice Event emitted on treasury address update * @param treasury The new treasury address */ event TreasuryUpdated(address indexed treasury); /** * @notice Event emitted on fee percent update * @param feePercent The new fee percent */ event FeePercentUpdated(uint16 feePercent); /** * @notice Event emitted on average reward per second update * @param avgRewardPerSecond The new average reward per second */ event AvgRewardPerSecondUpdated(uint256 avgRewardPerSecond); /** * @notice Event emitted on keeper address update * @param keeper The new keeper address */ event KeeperUpdated(address keeper); /** * @notice The OsToken capacity * @return The amount after which the OsToken stops accepting deposits */ function capacity() external view returns (uint256); /** * @notice The DAO treasury address that receives OsToken fees * @return The address of the treasury */ function treasury() external view returns (address); /** * @notice The fee percent (multiplied by 100) * @return The fee percent applied by the OsToken on the rewards */ function feePercent() external view returns (uint64); /** * @notice The address that can update avgRewardPerSecond * @return The address of the keeper contract */ function keeper() external view returns (address); /** * @notice The average reward per second used to mint OsToken rewards * @return The average reward per second earned by the Vaults */ function avgRewardPerSecond() external view returns (uint256); /** * @notice The fee per share used for calculating the fee for every position * @return The cumulative fee per share */ function cumulativeFeePerShare() external view returns (uint256); /** * @notice The total number of shares controlled by the OsToken * @return The total number of shares */ function totalShares() external view returns (uint256); /** * @notice Total assets controlled by the OsToken * @return The total amount of the underlying asset that is "managed" by OsToken */ function totalAssets() external view returns (uint256); /** * @notice Converts shares to assets * @param assets The amount of assets to convert to shares * @return shares The amount of shares that the OsToken would exchange for the amount of assets provided */ function convertToShares(uint256 assets) external view returns (uint256 shares); /** * @notice Converts assets to shares * @param shares The amount of shares to convert to assets * @return assets The amount of assets that the OsToken would exchange for the amount of shares provided */ function convertToAssets(uint256 shares) external view returns (uint256 assets); /** * @notice Updates rewards and treasury fee checkpoint for the OsToken */ function updateState() external; /** * @notice Mint OsToken shares. Can only be called by the registered vault. * @param receiver The address that will receive the shares * @param shares The amount of shares to mint * @return assets The amount of assets minted */ function mintShares(address receiver, uint256 shares) external returns (uint256 assets); /** * @notice Burn shares for withdrawn assets. Can only be called by the registered vault. * @param owner The address that owns the shares * @param shares The amount of shares to burn * @return assets The amount of assets withdrawn */ function burnShares(address owner, uint256 shares) external returns (uint256 assets); /** * @notice Update treasury address. Can only be called by the owner. * @param _treasury The new treasury address */ function setTreasury(address _treasury) external; /** * @notice Update capacity. Can only be called by the owner. * @param _capacity The amount after which the OsToken stops accepting deposits */ function setCapacity(uint256 _capacity) external; /** * @notice Update fee percent. Can only be called by the owner. Cannot be larger than 10 000 (100%). * @param _feePercent The new fee percent */ function setFeePercent(uint16 _feePercent) external; /** * @notice Update keeper address. Can only be called by the owner. * @param _keeper The new keeper address */ function setKeeper(address _keeper) external; /** * @notice Updates average reward per second. Can only be called by the keeper. * @param _avgRewardPerSecond The new average reward per second */ function setAvgRewardPerSecond(uint256 _avgRewardPerSecond) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IMulticall} from './IMulticall.sol'; /** * @title IOsTokenVaultEscrow * @author StakeWise * @notice Interface for OsTokenVaultEscrow contract */ interface IOsTokenVaultEscrow is IMulticall { /** * @notice Struct to store the escrow position details * @param owner The address of the assets owner * @param exitedAssets The amount of assets exited and ready to be claimed * @param osTokenShares The amount of osToken shares * @param cumulativeFeePerShare The cumulative fee per share used to calculate the osToken fee */ struct Position { address owner; uint96 exitedAssets; uint128 osTokenShares; uint128 cumulativeFeePerShare; } /** * @notice Event emitted on position creation * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param owner The address of the assets owner * @param osTokenShares The amount of osToken shares * @param cumulativeFeePerShare The cumulative fee per share used to calculate the osToken fee */ event PositionCreated( address indexed vault, uint256 indexed exitPositionTicket, address owner, uint256 osTokenShares, uint256 cumulativeFeePerShare ); /** * @notice Event emitted on assets exit processing * @param vault The address of the vault * @param caller The address of the caller * @param exitPositionTicket The exit position ticket * @param exitedAssets The amount of exited assets claimed */ event ExitedAssetsProcessed( address indexed vault, address indexed caller, uint256 indexed exitPositionTicket, uint256 exitedAssets ); /** * @notice Event emitted on osToken liquidation * @param caller The address of the function caller * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param receiver The address of the receiver of the liquidated assets * @param osTokenShares The amount of osToken shares to liquidate * @param receivedAssets The amount of assets received */ event OsTokenLiquidated( address indexed caller, address indexed vault, uint256 indexed exitPositionTicket, address receiver, uint256 osTokenShares, uint256 receivedAssets ); /** * @notice Event emitted on osToken redemption * @param caller The address of the function caller * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param receiver The address of the receiver of the redeemed assets * @param osTokenShares The amount of osToken shares to redeem * @param receivedAssets The amount of assets received */ event OsTokenRedeemed( address indexed caller, address indexed vault, uint256 indexed exitPositionTicket, address receiver, uint256 osTokenShares, uint256 receivedAssets ); /** * @notice Event emitted on exited assets claim * @param receiver The address of the receiver of the exited assets * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param osTokenShares The amount of osToken shares burned * @param assets The amount of assets claimed */ event ExitedAssetsClaimed( address indexed receiver, address indexed vault, uint256 indexed exitPositionTicket, uint256 osTokenShares, uint256 assets ); /** * @notice Event emitted on liquidation configuration update * @param liqThresholdPercent The liquidation threshold percent * @param liqBonusPercent The liquidation bonus percent */ event LiqConfigUpdated(uint64 liqThresholdPercent, uint256 liqBonusPercent); /** * @notice Event emitted on authenticator update * @param newAuthenticator The address of the new authenticator */ event AuthenticatorUpdated(address newAuthenticator); /** * @notice The liquidation threshold percent * @return The liquidation threshold percent starting from which the osToken shares can be liquidated */ function liqThresholdPercent() external view returns (uint64); /** * @notice The liquidation bonus percent * @return The liquidation bonus percent paid for liquidating the osToken shares */ function liqBonusPercent() external view returns (uint256); /** * @notice The address of the authenticator * @return The address of the authenticator contract */ function authenticator() external view returns (address); /** * @notice Get the position details * @param vault The address of the vault * @param positionTicket The exit position ticket * @return owner The address of the assets owner * @return exitedAssets The amount of assets exited and ready to be claimed * @return osTokenShares The amount of osToken shares */ function getPosition( address vault, uint256 positionTicket ) external view returns (address, uint256, uint256); /** * @notice Registers the new escrow position * @param owner The address of the exited assets owner * @param exitPositionTicket The exit position ticket * @param osTokenShares The amount of osToken shares * @param cumulativeFeePerShare The cumulative fee per share used to calculate the osToken fee */ function register( address owner, uint256 exitPositionTicket, uint256 osTokenShares, uint256 cumulativeFeePerShare ) external; /** * @notice Claims exited assets from the vault to the escrow * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param timestamp The timestamp of the exit * @param exitQueueIndex The index of the exit in the queue */ function processExitedAssets( address vault, uint256 exitPositionTicket, uint256 timestamp, uint256 exitQueueIndex ) external; /** * @notice Claims the exited assets from the escrow to the owner. Can only be called by the position owner. * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param osTokenShares The amount of osToken shares to burn * @return claimedAssets The amount of assets claimed */ function claimExitedAssets( address vault, uint256 exitPositionTicket, uint256 osTokenShares ) external returns (uint256 claimedAssets); /** * @notice Liquidates the osToken shares * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param osTokenShares The amount of osToken shares to liquidate * @param receiver The address of the receiver of the liquidated assets */ function liquidateOsToken( address vault, uint256 exitPositionTicket, uint256 osTokenShares, address receiver ) external; /** * @notice Redeems the osToken shares. Can only be called by the osToken redeemer. * @param vault The address of the vault * @param exitPositionTicket The exit position ticket * @param osTokenShares The amount of osToken shares to redeem * @param receiver The address of the receiver of the redeemed assets */ function redeemOsToken( address vault, uint256 exitPositionTicket, uint256 osTokenShares, address receiver ) external; /** * @notice Updates the authenticator. Can only be called by the owner. * @param newAuthenticator The address of the new authenticator */ function setAuthenticator(address newAuthenticator) external; /** * @notice Updates the liquidation configuration. Can only be called by the owner. * @param _liqThresholdPercent The liquidation threshold percent * @param _liqBonusPercent The liquidation bonus percent */ function updateLiqConfig(uint64 _liqThresholdPercent, uint256 _liqBonusPercent) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IOsTokenVaultEscrowAuth * @author StakeWise * @notice Interface for OsTokenVaultEscrowAuth contract */ interface IOsTokenVaultEscrowAuth { /** * @notice Check if the caller can register the exit position * @param vault The address of the vault * @param owner The address of the assets owner * @param exitPositionTicket The exit position ticket * @param osTokenShares The amount of osToken shares to burn * @return True if the caller can register the exit position */ function canRegister( address vault, address owner, uint256 exitPositionTicket, uint256 osTokenShares ) external view returns (bool); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title IVaultState * @author StakeWise * @notice Defines the interface for the VaultAdmin contract */ interface IVaultAdmin { /** * @notice Event emitted on metadata ipfs hash update * @param caller The address of the function caller * @param metadataIpfsHash The new metadata IPFS hash */ event MetadataUpdated(address indexed caller, string metadataIpfsHash); /** * @notice The Vault admin * @return The address of the Vault admin */ function admin() external view returns (address); /** * @notice Function for updating the metadata IPFS hash. Can only be called by Vault admin. * @param metadataIpfsHash The new metadata IPFS hash */ function setMetadata(string calldata metadataIpfsHash) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultState} from './IVaultState.sol'; /** * @title IVaultEnterExit * @author StakeWise * @notice Defines the interface for the VaultEnterExit contract */ interface IVaultEnterExit is IVaultState { /** * @notice Event emitted on deposit * @param caller The address that called the deposit function * @param receiver The address that received the shares * @param assets The number of assets deposited by the caller * @param shares The number of shares received * @param referrer The address of the referrer */ event Deposited( address indexed caller, address indexed receiver, uint256 assets, uint256 shares, address referrer ); /** * @notice Event emitted on redeem * @param owner The address that owns the shares * @param receiver The address that received withdrawn assets * @param assets The total number of withdrawn assets * @param shares The total number of withdrawn shares */ event Redeemed(address indexed owner, address indexed receiver, uint256 assets, uint256 shares); /** * @notice Event emitted on shares added to the exit queue * @param owner The address that owns the shares * @param receiver The address that will receive withdrawn assets * @param positionTicket The exit queue ticket that was assigned to the position * @param shares The number of shares that queued for the exit */ event ExitQueueEntered( address indexed owner, address indexed receiver, uint256 positionTicket, uint256 shares ); /** * @notice Event emitted on shares added to the V2 exit queue (deprecated) * @param owner The address that owns the shares * @param receiver The address that will receive withdrawn assets * @param positionTicket The exit queue ticket that was assigned to the position * @param shares The number of shares that queued for the exit * @param assets The number of assets that queued for the exit */ event V2ExitQueueEntered( address indexed owner, address indexed receiver, uint256 positionTicket, uint256 shares, uint256 assets ); /** * @notice Event emitted on claim of the exited assets * @param receiver The address that has received withdrawn assets * @param prevPositionTicket The exit queue ticket received after the `enterExitQueue` call * @param newPositionTicket The new exit queue ticket in case not all the shares were withdrawn. Otherwise 0. * @param withdrawnAssets The total number of assets withdrawn */ event ExitedAssetsClaimed( address indexed receiver, uint256 prevPositionTicket, uint256 newPositionTicket, uint256 withdrawnAssets ); /** * @notice Locks shares to the exit queue. The shares continue earning rewards until they will be burned by the Vault. * @param shares The number of shares to lock * @param receiver The address that will receive assets upon withdrawal * @return positionTicket The position ticket of the exit queue. Returns uint256 max if no ticket created. */ function enterExitQueue( uint256 shares, address receiver ) external returns (uint256 positionTicket); /** * @notice Get the exit queue index to claim exited assets from * @param positionTicket The exit queue position ticket to get the index for * @return The exit queue index that should be used to claim exited assets. * Returns -1 in case such index does not exist. */ function getExitQueueIndex(uint256 positionTicket) external view returns (int256); /** * @notice Calculates the number of shares and assets that can be claimed from the exit queue. * @param receiver The address that will receive assets upon withdrawal * @param positionTicket The exit queue ticket received after the `enterExitQueue` call * @param timestamp The timestamp when the shares entered the exit queue * @param exitQueueIndex The exit queue index at which the shares were burned. It can be looked up by calling `getExitQueueIndex`. * @return leftTickets The number of tickets left in the queue * @return exitedTickets The number of tickets that have already exited * @return exitedAssets The number of assets that can be claimed */ function calculateExitedAssets( address receiver, uint256 positionTicket, uint256 timestamp, uint256 exitQueueIndex ) external view returns (uint256 leftTickets, uint256 exitedTickets, uint256 exitedAssets); /** * @notice Claims assets that were withdrawn by the Vault. It can be called only after the `enterExitQueue` call by the `receiver`. * @param positionTicket The exit queue ticket received after the `enterExitQueue` call * @param timestamp The timestamp when the assets entered the exit queue * @param exitQueueIndex The exit queue index at which the shares were burned. * It can be looked up by calling `getExitQueueIndex`. */ function claimExitedAssets( uint256 positionTicket, uint256 timestamp, uint256 exitQueueIndex ) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IVaultAdmin} from './IVaultAdmin.sol'; /** * @title IVaultFee * @author StakeWise * @notice Defines the interface for the VaultFee contract */ interface IVaultFee is IVaultAdmin { /** * @notice Event emitted on fee recipient update * @param caller The address of the function caller * @param feeRecipient The address of the new fee recipient */ event FeeRecipientUpdated(address indexed caller, address indexed feeRecipient); /** * @notice The Vault's fee recipient * @return The address of the Vault's fee recipient */ function feeRecipient() external view returns (address); /** * @notice The Vault's fee percent in BPS * @return The fee percent applied by the Vault on the rewards */ function feePercent() external view returns (uint16); /** * @notice Function for updating the fee recipient address. Can only be called by the admin. * @param _feeRecipient The address of the new fee recipient */ function setFeeRecipient(address _feeRecipient) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {IKeeperRewards} from './IKeeperRewards.sol'; import {IVaultFee} from './IVaultFee.sol'; /** * @title IVaultState * @author StakeWise * @notice Defines the interface for the VaultState contract */ interface IVaultState is IVaultFee { /** * @notice Event emitted on checkpoint creation * @param shares The number of burned shares * @param assets The amount of exited assets */ event CheckpointCreated(uint256 shares, uint256 assets); /** * @notice Event emitted on minting fee recipient shares * @param receiver The address of the fee recipient * @param shares The number of minted shares * @param assets The amount of minted assets */ event FeeSharesMinted(address receiver, uint256 shares, uint256 assets); /** * @notice Event emitted when exiting assets are penalized * @param penalty The total penalty amount */ event ExitingAssetsPenalized(uint256 penalty); /** * @notice Total assets in the Vault * @return The total amount of the underlying asset that is "managed" by Vault */ function totalAssets() external view returns (uint256); /** * @notice Function for retrieving total shares * @return The amount of shares in existence */ function totalShares() external view returns (uint256); /** * @notice The Vault's capacity * @return The amount after which the Vault stops accepting deposits */ function capacity() external view returns (uint256); /** * @notice Total assets available in the Vault. They can be staked or withdrawn. * @return The total amount of withdrawable assets */ function withdrawableAssets() external view returns (uint256); /** * @notice Queued Shares * @return The total number of shares queued for exit */ function queuedShares() external view returns (uint128); /** * @notice Returns the number of shares held by an account * @param account The account for which to look up the number of shares it has, i.e. its balance * @return The number of shares held by the account */ function getShares(address account) external view returns (uint256); /** * @notice Converts assets to shares * @param assets The amount of assets to convert to shares * @return shares The amount of shares that the Vault would exchange for the amount of assets provided */ function convertToShares(uint256 assets) external view returns (uint256 shares); /** * @notice Converts shares to assets * @param shares The amount of shares to convert to assets * @return assets The amount of assets that the Vault would exchange for the amount of shares provided */ function convertToAssets(uint256 shares) external view returns (uint256 assets); /** * @notice Check whether state update is required * @return `true` if state update is required, `false` otherwise */ function isStateUpdateRequired() external view returns (bool); /** * @notice Updates the total amount of assets in the Vault and its exit queue * @param harvestParams The parameters for harvesting Keeper rewards */ function updateState(IKeeperRewards.HarvestParams calldata harvestParams) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; /** * @title Errors * @author StakeWise * @notice Contains all the custom errors */ library Errors { error AccessDenied(); error InvalidShares(); error InvalidAssets(); error ZeroAddress(); error InsufficientAssets(); error CapacityExceeded(); error InvalidCapacity(); error InvalidSecurityDeposit(); error InvalidFeeRecipient(); error InvalidFeePercent(); error NotHarvested(); error NotCollateralized(); error InvalidProof(); error LowLtv(); error InvalidPosition(); error InvalidHealthFactor(); error InvalidReceivedAssets(); error InvalidTokenMeta(); error UpgradeFailed(); error InvalidValidators(); error DeadlineExpired(); error PermitInvalidSigner(); error InvalidValidatorsRegistryRoot(); error InvalidVault(); error AlreadyAdded(); error AlreadyRemoved(); error InvalidOracles(); error NotEnoughSignatures(); error InvalidOracle(); error TooEarlyUpdate(); error InvalidAvgRewardPerSecond(); error InvalidRewardsRoot(); error HarvestFailed(); error LiquidationDisabled(); error InvalidLiqThresholdPercent(); error InvalidLiqBonusPercent(); error InvalidLtvPercent(); error InvalidCheckpointIndex(); error InvalidCheckpointValue(); error MaxOraclesExceeded(); error ExitRequestNotProcessed(); error ValueNotChanged(); error InvalidWithdrawalCredentials(); error EigenPodNotFound(); error InvalidQueuedShares(); error FlashLoanFailed(); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; import {Math} from '@openzeppelin/contracts/utils/math/Math.sol'; import {SafeCast} from '@openzeppelin/contracts/utils/math/SafeCast.sol'; import {Ownable2Step, Ownable} from '@openzeppelin/contracts/access/Ownable2Step.sol'; import {IOsTokenVaultEscrow} from '../interfaces/IOsTokenVaultEscrow.sol'; import {IOsTokenVaultController} from '../interfaces/IOsTokenVaultController.sol'; import {IVaultEnterExit} from '../interfaces/IVaultEnterExit.sol'; import {IOsTokenConfig} from '../interfaces/IOsTokenConfig.sol'; import {IOsTokenVaultEscrowAuth} from '../interfaces/IOsTokenVaultEscrowAuth.sol'; import {Errors} from '../libraries/Errors.sol'; import {Multicall} from '../base/Multicall.sol'; /** * @title OsTokenVaultEscrow * @author StakeWise * @notice Used for initiating assets exits from the vault without burning osToken */ abstract contract OsTokenVaultEscrow is Ownable2Step, Multicall, IOsTokenVaultEscrow { uint256 private constant _maxPercent = 1e18; uint256 private constant _wad = 1e18; uint256 private constant _hfLiqThreshold = 1e18; IOsTokenVaultController private immutable _osTokenVaultController; IOsTokenConfig private immutable _osTokenConfig; mapping(address vault => mapping(uint256 positionTicket => Position)) private _positions; /// @inheritdoc IOsTokenVaultEscrow uint256 public override liqBonusPercent; /// @inheritdoc IOsTokenVaultEscrow address public override authenticator; /// @inheritdoc IOsTokenVaultEscrow uint64 public override liqThresholdPercent; /** * @dev Constructor * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param initialOwner The address of the contract owner * @param _authenticator The address of the OsTokenVaultEscrowAuth contract * @param _liqThresholdPercent The liquidation threshold percent * @param _liqBonusPercent The liquidation bonus percent */ constructor( address osTokenVaultController, address osTokenConfig, address initialOwner, address _authenticator, uint64 _liqThresholdPercent, uint256 _liqBonusPercent ) Ownable(msg.sender) { _osTokenVaultController = IOsTokenVaultController(osTokenVaultController); _osTokenConfig = IOsTokenConfig(osTokenConfig); updateLiqConfig(_liqThresholdPercent, _liqBonusPercent); setAuthenticator(_authenticator); _transferOwnership(initialOwner); } /// @inheritdoc IOsTokenVaultEscrow function getPosition( address vault, uint256 positionTicket ) external view returns (address, uint256, uint256) { Position memory position = _positions[vault][positionTicket]; if (position.osTokenShares != 0) { _syncPositionFee(position); } return (position.owner, position.exitedAssets, position.osTokenShares); } /// @inheritdoc IOsTokenVaultEscrow function register( address owner, uint256 exitPositionTicket, uint256 osTokenShares, uint256 cumulativeFeePerShare ) external override { // check if caller has permission if ( !IOsTokenVaultEscrowAuth(authenticator).canRegister( msg.sender, owner, exitPositionTicket, osTokenShares ) ) { revert Errors.AccessDenied(); } // check owner and shares are not zero if (owner == address(0)) revert Errors.ZeroAddress(); if (osTokenShares == 0) revert Errors.InvalidShares(); // create new position _positions[msg.sender][exitPositionTicket] = Position({ owner: owner, exitedAssets: 0, osTokenShares: SafeCast.toUint128(osTokenShares), cumulativeFeePerShare: SafeCast.toUint128(cumulativeFeePerShare) }); // emit event emit PositionCreated( msg.sender, exitPositionTicket, owner, osTokenShares, cumulativeFeePerShare ); } /// @inheritdoc IOsTokenVaultEscrow function processExitedAssets( address vault, uint256 exitPositionTicket, uint256 timestamp, uint256 exitQueueIndex ) external override { // get position Position storage position = _positions[vault][exitPositionTicket]; if (position.owner == address(0)) revert Errors.InvalidPosition(); // claim exited assets (uint256 leftTickets, , uint256 exitedAssets) = IVaultEnterExit(vault).calculateExitedAssets( address(this), exitPositionTicket, timestamp, uint256(exitQueueIndex) ); // the exit request must be fully processed (1 ticket could be a rounding error) if (leftTickets > 1) revert Errors.ExitRequestNotProcessed(); IVaultEnterExit(vault).claimExitedAssets( exitPositionTicket, timestamp, uint256(exitQueueIndex) ); // update position position.exitedAssets = SafeCast.toUint96(exitedAssets); // emit event emit ExitedAssetsProcessed(vault, msg.sender, exitPositionTicket, exitedAssets); } /// @inheritdoc IOsTokenVaultEscrow function claimExitedAssets( address vault, uint256 exitPositionTicket, uint256 osTokenShares ) external override returns (uint256 claimedAssets) { // burn osToken shares _osTokenVaultController.burnShares(msg.sender, osTokenShares); // fetch user position Position memory position = _positions[vault][exitPositionTicket]; if (msg.sender != position.owner) revert Errors.AccessDenied(); // check whether position exists and there are enough osToken shares _syncPositionFee(position); if (position.osTokenShares == 0 || position.osTokenShares < osTokenShares) { revert Errors.InvalidShares(); } // calculate assets to withdraw if (position.osTokenShares != osTokenShares) { claimedAssets = Math.mulDiv(position.exitedAssets, osTokenShares, position.osTokenShares); // update position osTokenShares position.exitedAssets -= SafeCast.toUint96(claimedAssets); position.osTokenShares -= SafeCast.toUint128(osTokenShares); _positions[vault][exitPositionTicket] = position; } else { claimedAssets = position.exitedAssets; // remove position as it is fully processed delete _positions[vault][exitPositionTicket]; } if (claimedAssets == 0) revert Errors.ExitRequestNotProcessed(); // transfer assets _transferAssets(position.owner, claimedAssets); // emit event emit ExitedAssetsClaimed(msg.sender, vault, exitPositionTicket, osTokenShares, claimedAssets); } /// @inheritdoc IOsTokenVaultEscrow function liquidateOsToken( address vault, uint256 exitPositionTicket, uint256 osTokenShares, address receiver ) external override { uint256 receivedAssets = _redeemOsToken( vault, exitPositionTicket, receiver, osTokenShares, true ); emit OsTokenLiquidated( msg.sender, vault, exitPositionTicket, receiver, osTokenShares, receivedAssets ); } /// @inheritdoc IOsTokenVaultEscrow function redeemOsToken( address vault, uint256 exitPositionTicket, uint256 osTokenShares, address receiver ) external override { if (msg.sender != _osTokenConfig.redeemer()) revert Errors.AccessDenied(); uint256 receivedAssets = _redeemOsToken( vault, exitPositionTicket, receiver, osTokenShares, false ); emit OsTokenRedeemed( msg.sender, vault, exitPositionTicket, receiver, osTokenShares, receivedAssets ); } /// @inheritdoc IOsTokenVaultEscrow function setAuthenticator(address newAuthenticator) public override onlyOwner { if (authenticator == newAuthenticator) revert Errors.ValueNotChanged(); authenticator = newAuthenticator; emit AuthenticatorUpdated(newAuthenticator); } /// @inheritdoc IOsTokenVaultEscrow function updateLiqConfig( uint64 _liqThresholdPercent, uint256 _liqBonusPercent ) public override onlyOwner { // validate liquidation threshold percent if (_liqThresholdPercent == 0 || _liqThresholdPercent >= _maxPercent) { revert Errors.InvalidLiqThresholdPercent(); } // validate liquidation bonus percent if ( _liqBonusPercent < _maxPercent || Math.mulDiv(_liqThresholdPercent, _liqBonusPercent, _maxPercent) > _maxPercent ) { revert Errors.InvalidLiqBonusPercent(); } // update config liqThresholdPercent = _liqThresholdPercent; liqBonusPercent = _liqBonusPercent; // emit event emit LiqConfigUpdated(_liqThresholdPercent, _liqBonusPercent); } /** * @dev Internal function for redeeming osToken shares * @param vault The address of the vault * @param exitPositionTicket The position ticket of the exit queue * @param receiver The address of the receiver of the redeemed assets * @param osTokenShares The amount of osToken shares to redeem * @param isLiquidation Whether the redeem is a liquidation * @return receivedAssets The amount of assets received */ function _redeemOsToken( address vault, uint256 exitPositionTicket, address receiver, uint256 osTokenShares, bool isLiquidation ) private returns (uint256 receivedAssets) { if (receiver == address(0)) revert Errors.ZeroAddress(); // update osToken state for gas efficiency _osTokenVaultController.updateState(); // fetch user position Position memory position = _positions[vault][exitPositionTicket]; if (position.osTokenShares == 0) revert Errors.InvalidPosition(); _syncPositionFee(position); // calculate received assets if (isLiquidation) { receivedAssets = Math.mulDiv( _osTokenVaultController.convertToAssets(osTokenShares), liqBonusPercent, _maxPercent ); } else { receivedAssets = _osTokenVaultController.convertToAssets(osTokenShares); } { // check whether received assets are valid if (receivedAssets > position.exitedAssets) { revert Errors.InvalidReceivedAssets(); } if (isLiquidation) { // check health factor violation in case of liquidation uint256 mintedAssets = _osTokenVaultController.convertToAssets(position.osTokenShares); if ( Math.mulDiv( position.exitedAssets * _wad, liqThresholdPercent, mintedAssets * _maxPercent ) >= _hfLiqThreshold ) { revert Errors.InvalidHealthFactor(); } } } // reduce osToken supply _osTokenVaultController.burnShares(msg.sender, osTokenShares); // update position position.exitedAssets -= SafeCast.toUint96(receivedAssets); position.osTokenShares -= SafeCast.toUint128(osTokenShares); _positions[vault][exitPositionTicket] = position; // transfer assets to the receiver _transferAssets(receiver, receivedAssets); } /** * @dev Internal function for syncing the osToken fee * @param position The position to sync the fee for */ function _syncPositionFee(Position memory position) private view { // fetch current cumulative fee per share uint256 cumulativeFeePerShare = _osTokenVaultController.cumulativeFeePerShare(); // check whether fee is already up to date if (cumulativeFeePerShare == position.cumulativeFeePerShare) return; // add treasury fee to the position position.osTokenShares = SafeCast.toUint128( Math.mulDiv(position.osTokenShares, cumulativeFeePerShare, position.cumulativeFeePerShare) ); position.cumulativeFeePerShare = SafeCast.toUint128(cumulativeFeePerShare); } /** * @dev Internal function for transferring assets from the Vault to the receiver * @dev IMPORTANT: because control is transferred to the receiver, care must be * taken to not create reentrancy vulnerabilities. The Vault must follow the checks-effects-interactions pattern: * https://docs.soliditylang.org/en/v0.8.22/security-considerations.html#use-the-checks-effects-interactions-pattern * @param receiver The address that will receive the assets * @param assets The number of assets to transfer */ function _transferAssets(address receiver, uint256 assets) internal virtual; }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 200, "details": { "yul": true } }, "evmVersion": "shanghai", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"osTokenVaultController","type":"address"},{"internalType":"address","name":"osTokenConfig","type":"address"},{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"address","name":"_authenticator","type":"address"},{"internalType":"uint64","name":"_liqThresholdPercent","type":"uint64"},{"internalType":"uint256","name":"_liqBonusPercent","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessDenied","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ExitRequestNotProcessed","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidHealthFactor","type":"error"},{"inputs":[],"name":"InvalidLiqBonusPercent","type":"error"},{"inputs":[],"name":"InvalidLiqThresholdPercent","type":"error"},{"inputs":[],"name":"InvalidPosition","type":"error"},{"inputs":[],"name":"InvalidReceivedAssets","type":"error"},{"inputs":[],"name":"InvalidShares","type":"error"},{"inputs":[],"name":"MathOverflowedMulDiv","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":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"AssetsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAuthenticator","type":"address"}],"name":"AuthenticatorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"uint256","name":"exitPositionTicket","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"ExitedAssetsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"uint256","name":"exitPositionTicket","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"exitedAssets","type":"uint256"}],"name":"ExitedAssetsProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"liqThresholdPercent","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"liqBonusPercent","type":"uint256"}],"name":"LiqConfigUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"uint256","name":"exitPositionTicket","type":"uint256"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"receivedAssets","type":"uint256"}],"name":"OsTokenLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"uint256","name":"exitPositionTicket","type":"uint256"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"receivedAssets","type":"uint256"}],"name":"OsTokenRedeemed","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":"vault","type":"address"},{"indexed":true,"internalType":"uint256","name":"exitPositionTicket","type":"uint256"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cumulativeFeePerShare","type":"uint256"}],"name":"PositionCreated","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"authenticator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"exitPositionTicket","type":"uint256"},{"internalType":"uint256","name":"osTokenShares","type":"uint256"}],"name":"claimExitedAssets","outputs":[{"internalType":"uint256","name":"claimedAssets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"positionTicket","type":"uint256"}],"name":"getPosition","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liqBonusPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liqThresholdPercent","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"exitPositionTicket","type":"uint256"},{"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"liquidateOsToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"exitPositionTicket","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"exitQueueIndex","type":"uint256"}],"name":"processExitedAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"exitPositionTicket","type":"uint256"},{"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"redeemOsToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"exitPositionTicket","type":"uint256"},{"internalType":"uint256","name":"osTokenShares","type":"uint256"},{"internalType":"uint256","name":"cumulativeFeePerShare","type":"uint256"}],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAuthenticator","type":"address"}],"name":"setAuthenticator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_liqThresholdPercent","type":"uint64"},{"internalType":"uint256","name":"_liqBonusPercent","type":"uint256"}],"name":"updateLiqConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60c0346200025c57601f62001f1638819003918201601f1916830192916001600160401b03918285118486101762000260578160c092859260409788528339810103126200025c57620000528262000274565b620000606020840162000274565b916200006e85850162000274565b936200007d6060820162000274565b906080810151928316908184036200025c5760a001519360015f5533156200024557620000aa3362000289565b6001600160a01b0390811660805294851660a052620000c8620002dc565b8015801562000232575b6200022157670de0b6b3a76400008085109081156200020b575b50620001fa5760058054600160a01b600160e01b0360a09590951b94909416600160a01b600160e01b0319851681179091556004859055875191825260208201949094528491907ff8333ae7adea4c8a83c7ed352346665b55517daecce9ddb81f555e9f6c96cd6b908890a162000162620002dc565b168093821614620001e9576001600160e01b0319161781176005558251908152620001b491907f83292ae03f07801d2323041a63198dd4d11efb58fdd68f383a752b467c529f3790602090a162000289565b51611b8490816200039282396080518181816101f001528181610586015281816116760152611968015260a0518161111e0152f35b8451638c8728c760e01b8152600490fd5b865163083887e960e21b8152600490fd5b905062000219858362000309565b115f620000ec565b865163152b042360e21b8152600490fd5b50670de0b6b3a7640000811015620000d2565b8751631e4fbdf760e01b81525f6004820152602490fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036200025c57565b600280546001600160a01b0319908116909155600180549182166001600160a01b0393841690811790915591167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b6001546001600160a01b03163303620002f157565b60405163118cdaa760e01b8152336004820152602490fd5b90808202905f19818409908280831092039180830392146200038057670de0b6b3a764000090828211156200036e577faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac10669940990828211900360ee1b910360121c170290565b60405163227bc15360e01b8152600490fd5b5050670de0b6b3a76400009150049056fe60806040526004361015610022575b3615610018575f80fd5b610020611632565b005b5f3560e01c80630c4f735f146101315780630ff1ff9a1461012c578063145d7632146101275780632335c76b146101225780632b9acefa1461011d5780633a774b48146101185780633adbb5af146101135780636bf8e70e1461010e578063715018a61461010957806379ba5097146101045780638da5cb5b146100ff57806398e99bb7146100fa578063aa4fe718146100f5578063ac9650d8146100f0578063bd69176f146100eb578063e30c3978146100e65763f2fde38b0361000e5761121b565b6111f3565b6110eb565b611086565b610eca565b610d2b565b610d03565b610c81565b610c1c565b610b91565b610a9c565b6108ea565b610560565b610508565b61019b565b610161565b610144565b5f91031261014057565b5f80fd5b34610140575f366003190112610140576020600454604051908152f35b34610140575f3660031901126101405760206001600160401b0360055460a01c16604051908152f35b6001600160a01b0381160361014057565b34610140576060366003190112610140576004356101b88161018a565b60408051633b9e9f0160e21b81523360048201526044803560248084018290526001600160a01b03959194939035926020908290815f7f00000000000000000000000000000000000000000000000000000000000000008b165af18015610503576104d4575b5061025261024d836102408460018060a01b03165f52600360205260405f2090565b905f5260205260405f2090565b61131c565b8051909490610271906001600160a01b03165b6001600160a01b031690565b33036104c35761028085611660565b838501946001600160801b03958661029f82516001600160801b031690565b168381159182156104b9575b50506104a85782876102c483516001600160801b031690565b1614610450576103609061033761030d6020850199866001600160601b036102f38d516001600160601b031690565b9261030587516001600160801b031690565b1692166117d7565b9861032a61031a8b611857565b82516001600160601b0316611372565b6001600160601b03169052565b6103536103438561188a565b82516001600160801b0316611390565b6001600160801b03169052565b6103d081610382866102408760018060a01b03165f52600360205260405f2090565b8151602083015160a01b6001600160a01b0319166001600160a01b0391909116178155906001906001600160801b036040820151169060606001600160801b031991015160801b1617910155565b851561043f575161043b967fd771679d1dffa1ab8c532072cfddf3582fd9734877673490ce98426f15dfb4ce916104169088906001600160a01b03166118bd565b6118bd565b85519283526020830187905292909216913391604090a4519081529081906020820190565b0390f35b8451630e3d8e8d60e11b8152600490fd5b50945061047661046a60208701516001600160601b031690565b6001600160601b031690565b946104a3610498856102408660018060a01b03165f52600360205260405f2090565b60015f918281550155565b6103d0565b8551636edcc52360e01b8152600490fd5b109050835f6102ab565b8351634ca8886760e01b8152600490fd5b6104f59060203d6020116104fc575b6104ed81836112d2565b8101906112f3565b505f61021e565b503d6104e3565b611302565b34610140575f366003190112610140576005546040516001600160a01b039091168152602090f35b6080906003190112610140576004356105488161018a565b90602435906044359060643561055d8161018a565b90565b346101405761056e36610530565b91929091906001600160a01b03808316156108b157807f00000000000000000000000000000000000000000000000000000000000000001691823b15610140576040928351631d8557d760e01b81526004905f81838183875af1801561050357610898575b506105f561024d896102408660018060a01b03165f52600360205260405f2090565b94808601956001600160801b0361061388516001600160801b031690565b161561088a578061062661064a92611660565b8251946303d1689d60e11b958681528b818060209687938a83019190602083019252565b0381855afa801561050357610669915f9161086d575b50865490611751565b948383019661068261046a89516001600160601b031690565b871161085e57846106c09161069e8d516001600160801b031690565b908851938492839283528683019190916001600160801b036020820193169052565b0381865afa90811561050357670de0b6b3a764000091610733915f91610841575b506107046001600160601b036106fe8c516001600160601b031690565b16611934565b6001600160401b0361072b6107256005546001600160401b039060a01c1690565b93611934565b9216906117d7565b1015610833578451633b9e9f0160e21b815233918101918252602082018d905291849183919082905f90829060400103925af1988915610503576107b1610810976107df956107bd947f36d2254ece9fe37664da4738f535058024f7b2ccb3d78abe69b705c1be2876ad9d610815575b505061032a61031a89611857565b6103536103438d61188a565b6001600160a01b0386165f908152600360205260409020610382908c90610240565b6107e982886118bd565b519384931696339684604091949392606082019560018060a01b0316825260208201520152565b0390a4005b8161082b92903d106104fc576104ed81836112d2565b505f806107a3565b845163185cfc6d60e11b8152fd5b6108589150873d89116104fc576104ed81836112d2565b5f6106e1565b50845163efda1a2760e01b8152fd5b6108849150853d87116104fc576104ed81836112d2565b5f610660565b505163673f032f60e11b8152fd5b806108a56108ab926112bf565b80610136565b5f6105d3565b60405163d92e233d60e01b8152600490fd5b6080906003190112610140576004356108db8161018a565b90602435906044359060643590565b34610140576108f8366108c3565b60055491939161091290610265906001600160a01b031681565b6040805163e0eb6af360e01b81523360048201526001600160a01b03851660248201526044810186905260648101879052909591602090829060849082905afa908115610503575f91610a6d575b5015610a5c576001600160a01b03831615610a4b578015610a3a57610a357fafda9316e64488bba379a6614bcee4516ef1793ee3844298c937b46b2cae5829939495610a106109ae8461188a565b6109f76109ba8761188a565b6109e76109c561130d565b6001600160a01b038c168152935f60208601526001600160801b031686850152565b6001600160801b03166060830152565b335f908152600360205260409020610382908a90610240565b51928392339684604091949392606082019560018060a01b0316825260208201520152565b0390a3005b8451636edcc52360e01b8152600490fd5b845163d92e233d60e01b8152600490fd5b8451634ca8886760e01b8152600490fd5b610a8f915060203d602011610a95575b610a8781836112d2565b8101906113a9565b5f610960565b503d610a7d565b34610140576040806003193601126101405760043590610abb8261018a565b60018060a01b038092165f526003602052805f206024355f5260205261043b815f20926001835194610aec8661129f565b80549283168652602086019260a01c83520154906001600160601b03610b5a610b4c610b3e6001600160801b03988987168982019781895260801c6060830152610b83575b516001600160a01b031690565b93516001600160601b031690565b93516001600160801b031690565b94516001600160a01b039092168252909116602082015292909116604083015281906060820190565b610b8c81611660565b610b31565b3461014057602036600319011261014057600435610bae8161018a565b610bb6611b3a565b6005546001600160a01b039182169181168214610c0a576001600160a01b03191681176005556040519081527f83292ae03f07801d2323041a63198dd4d11efb58fdd68f383a752b467c529f3790602090a1005b604051638c8728c760e01b8152600490fd5b34610140575f36600319011261014057610c34611b3a565b600280546001600160a01b03199081169091556001805491821690555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610140575f366003190112610140576002546001600160a01b033381831603610ceb576001600160601b0360a01b8092166002556001549133908316176001553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b60405163118cdaa760e01b8152336004820152602490fd5b34610140575f366003190112610140576001546040516001600160a01b039091168152602090f35b3461014057610d39366108c3565b610d5a836102408694959660018060a01b03165f52600360205260405f2090565b805490926001600160a01b0391821615610eb85760405163076b58b960e41b81523060048201526024810187905260448101869052606481018490529491169290606085608481875afa948515610503575f905f96610e83575b50600110610e7157833b156101405760405163434be96160e11b815260048101879052602481019190915260448101929092525f8260648183875af191821561050357610e2a92610e5e575b50610e0a84611857565b81546001600160a01b031660a09190911b6001600160a01b031916179055565b60405191825233917fda15728d9b7db891bd1235a1f54c14891973d2e88f4483636a7be928ccf5588c908060208101610810565b806108a5610e6b926112bf565b5f610e00565b604051630e3d8e8d60e11b8152600490fd5b60019650610ea9915060603d606011610eb1575b610ea181836112d2565b8101906113c1565b969050610db4565b503d610e97565b60405163673f032f60e11b8152600490fd5b34610140576040366003190112610140576004356001600160401b0381168082036101405760243590610efb611b3a565b80158015610fcb575b610fb957670de0b6b3a764000082818110928315610fa5575b505050610f93576005805467ffffffffffffffff60a01b191660a084901b67ffffffffffffffff60a01b161790557ff8333ae7adea4c8a83c7ed352346665b55517daecce9ddb81f555e9f6c96cd6b91610f7682600455565b604080516001600160401b039290921682526020820192909252a1005b60405163083887e960e21b8152600490fd5b610fb0929350611751565b115f8281610f1d565b60405163152b042360e21b8152600490fd5b50670de0b6b3a7640000811015610f04565b5f5b838110610fee5750505f910152565b8181015183820152602001610fdf565b9060209161101781518092818552858086019101610fdd565b601f01601f1916010190565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b8483106110585750505050505090565b9091929394958480611076600193603f198682030187528a51610ffe565b9801930193019194939290611048565b34610140576020366003190112610140576001600160401b036004358181116101405736602382011215610140578060040135918211610140573660248360051b830101116101405761043b9160246110df9201611570565b60405191829182611023565b34610140576110f936610530565b60405163057453a760e31b8152929391929091906001600160a01b03906020816004817f000000000000000000000000000000000000000000000000000000000000000086165afa80156105035782915f916111c4575b501633036111b257816108106111898686897ffebaeed78b2aaa8366a65cf2a811e7a20ce8c29f6563290cf5d4ece00379427897611951565b6040519384931696339684604091949392606082019560018060a01b0316825260208201520152565b604051634ca8886760e01b8152600490fd5b6111e6915060203d6020116111ec575b6111de81836112d2565b81019061161d565b5f611150565b503d6111d4565b34610140575f366003190112610140576002546040516001600160a01b039091168152602090f35b34610140576020366003190112610140576004356112388161018a565b611240611b3a565b600280546001600160a01b0319166001600160a01b039283169081179091556001549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b634e487b7160e01b5f52604160045260245ffd5b608081019081106001600160401b038211176112ba57604052565b61128b565b6001600160401b0381116112ba57604052565b90601f801991011681019081106001600160401b038211176112ba57604052565b90816020910312610140575190565b6040513d5f823e3d90fd5b6040519061131a8261129f565b565b906040516113298161129f565b82546001600160a01b038116825260a01c60208201526001909201546001600160801b038116604084015260801c6060830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160601b03918216908216039190821161138b57565b61135e565b6001600160801b03918216908216039190821161138b57565b90816020910312610140575180151581036101405790565b90816060910312610140578051916040602083015192015190565b6001600160401b0381116112ba5760051b60200190565b906113fd826113dc565b61140a60405191826112d2565b828152809261141b601f19916113dc565b01905f5b82811061142b57505050565b80606060208093850101520161141f565b634e487b7160e01b5f52603260045260245ffd5b91908110156114915760051b81013590601e19813603018212156101405701908135916001600160401b038311610140576020018236038113610140579190565b61143c565b908092918237015f815290565b6001600160401b0381116112ba57601f01601f191660200190565b3d156114e8573d906114cf826114a3565b916114dd60405193846112d2565b82523d5f602084013e565b606090565b602081830312610140578051906001600160401b038211610140570181601f8201121561014057805161151f816114a3565b9261152d60405194856112d2565b818452602082840101116101405761055d9160208085019101610fdd565b90602061055d928181520190610ffe565b80518210156114915760209160051b010190565b91909161157c836113f3565b925f5b81811061158b57505050565b5f80611598838587611450565b604093916115aa855180938193611496565b0390305af4906115b86114be565b91156115df5750906001916115cd828861155c565b526115d8818761155c565b500161157f565b90604481511061014057611619611604600492838101516024809183010191016114ed565b925162461bcd60e51b8152928392830161154b565b0390fd5b90816020910312610140575161055d8161018a565b6040513481527f09cea04c49f8b481a24e7cfff342f8b2a4ae27e595f0f3ba64ac8908efea5e0060203392a2565b60405163752a536d60e01b8152906020826004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa918215610503575f92611712575b5060608101906001600160801b0392836116cf84516001600160801b031690565b169182821461170b5761131a946103536117066103539585604061170696019461170086516001600160801b031690565b166117d7565b61188a565b5050505050565b61172c91925060203d6020116104fc576104ed81836112d2565b905f6116ae565b811561173d570490565b634e487b7160e01b5f52601260045260245ffd5b90808202905f19818409908280831092039180830392146117c657670de0b6b3a764000090828211156117b4577faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac10669940990828211900360ee1b910360121c170290565b60405163227bc15360e01b8152600490fd5b5050670de0b6b3a764000091500490565b9091828202915f198482099383808610950394808603951461184a57848311156117b457829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b50509061055d9250611733565b6001600160601b039081811161186b571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b6001600160801b039081811161189e571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b60025f54146119225760025f5581471061190a575f918291829182916001600160a01b03165af16118ec6114be565b50156118f85760015f55565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b90670de0b6b3a76400009182810292818404149015171561138b57565b92939290916001600160a01b03808216156108b1577f00000000000000000000000000000000000000000000000000000000000000001692833b15610140576040958651631d8557d760e01b81525f81600481838a5af1801561050357611b27575b506119d561024d836102408760018060a01b03165f52600360205260405f2090565b90878201926001600160801b036119f385516001600160801b031690565b1615611b1657611a0283611660565b88516303d1689d60e11b8152600481018390529560209081886024818c5afa978815610503575f98611af7575b50879a82860190611a4a61046a83516001600160601b031690565b8a11611ae75751633b9e9f0160e21b8152336004820152602481018690529983908b9060449082905f905af19687156105035761035361034361038297611706611ab09561131a9f8f61031a906104119f9b61032a936102409d611ac9575b5050611857565b6001600160a01b03165f90815260036020526040902090565b81611adf92903d106104fc576104ed81836112d2565b505f80611aa9565b5163efda1a2760e01b8152600490fd5b611b0f919850823d84116104fc576104ed81836112d2565b965f611a2f565b885163673f032f60e11b8152600490fd5b806108a5611b34926112bf565b5f6119b3565b6001546001600160a01b03163303610ceb5756fea26469706673582212207dd2347037e024c87551c91e253c373748a83703a673442ddffcf0f878f755ef64736f6c634300081600330000000000000000000000002a261e60fb14586b474c208b1b7ac6d0f5000306000000000000000000000000287d1e2a8de183a8bf8f2b09fa1340fbd766eb59000000000000000000000000144a98cb1cdbb23610501fe6108858d9b7d24934000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f00000000000000000000000000000000000000000000000000de0375f5d1f40000000000000000000000000000000000000000000000000000de0f48c233c4000
Deployed Bytecode
0x60806040526004361015610022575b3615610018575f80fd5b610020611632565b005b5f3560e01c80630c4f735f146101315780630ff1ff9a1461012c578063145d7632146101275780632335c76b146101225780632b9acefa1461011d5780633a774b48146101185780633adbb5af146101135780636bf8e70e1461010e578063715018a61461010957806379ba5097146101045780638da5cb5b146100ff57806398e99bb7146100fa578063aa4fe718146100f5578063ac9650d8146100f0578063bd69176f146100eb578063e30c3978146100e65763f2fde38b0361000e5761121b565b6111f3565b6110eb565b611086565b610eca565b610d2b565b610d03565b610c81565b610c1c565b610b91565b610a9c565b6108ea565b610560565b610508565b61019b565b610161565b610144565b5f91031261014057565b5f80fd5b34610140575f366003190112610140576020600454604051908152f35b34610140575f3660031901126101405760206001600160401b0360055460a01c16604051908152f35b6001600160a01b0381160361014057565b34610140576060366003190112610140576004356101b88161018a565b60408051633b9e9f0160e21b81523360048201526044803560248084018290526001600160a01b03959194939035926020908290815f7f0000000000000000000000002a261e60fb14586b474c208b1b7ac6d0f50003068b165af18015610503576104d4575b5061025261024d836102408460018060a01b03165f52600360205260405f2090565b905f5260205260405f2090565b61131c565b8051909490610271906001600160a01b03165b6001600160a01b031690565b33036104c35761028085611660565b838501946001600160801b03958661029f82516001600160801b031690565b168381159182156104b9575b50506104a85782876102c483516001600160801b031690565b1614610450576103609061033761030d6020850199866001600160601b036102f38d516001600160601b031690565b9261030587516001600160801b031690565b1692166117d7565b9861032a61031a8b611857565b82516001600160601b0316611372565b6001600160601b03169052565b6103536103438561188a565b82516001600160801b0316611390565b6001600160801b03169052565b6103d081610382866102408760018060a01b03165f52600360205260405f2090565b8151602083015160a01b6001600160a01b0319166001600160a01b0391909116178155906001906001600160801b036040820151169060606001600160801b031991015160801b1617910155565b851561043f575161043b967fd771679d1dffa1ab8c532072cfddf3582fd9734877673490ce98426f15dfb4ce916104169088906001600160a01b03166118bd565b6118bd565b85519283526020830187905292909216913391604090a4519081529081906020820190565b0390f35b8451630e3d8e8d60e11b8152600490fd5b50945061047661046a60208701516001600160601b031690565b6001600160601b031690565b946104a3610498856102408660018060a01b03165f52600360205260405f2090565b60015f918281550155565b6103d0565b8551636edcc52360e01b8152600490fd5b109050835f6102ab565b8351634ca8886760e01b8152600490fd5b6104f59060203d6020116104fc575b6104ed81836112d2565b8101906112f3565b505f61021e565b503d6104e3565b611302565b34610140575f366003190112610140576005546040516001600160a01b039091168152602090f35b6080906003190112610140576004356105488161018a565b90602435906044359060643561055d8161018a565b90565b346101405761056e36610530565b91929091906001600160a01b03808316156108b157807f0000000000000000000000002a261e60fb14586b474c208b1b7ac6d0f50003061691823b15610140576040928351631d8557d760e01b81526004905f81838183875af1801561050357610898575b506105f561024d896102408660018060a01b03165f52600360205260405f2090565b94808601956001600160801b0361061388516001600160801b031690565b161561088a578061062661064a92611660565b8251946303d1689d60e11b958681528b818060209687938a83019190602083019252565b0381855afa801561050357610669915f9161086d575b50865490611751565b948383019661068261046a89516001600160601b031690565b871161085e57846106c09161069e8d516001600160801b031690565b908851938492839283528683019190916001600160801b036020820193169052565b0381865afa90811561050357670de0b6b3a764000091610733915f91610841575b506107046001600160601b036106fe8c516001600160601b031690565b16611934565b6001600160401b0361072b6107256005546001600160401b039060a01c1690565b93611934565b9216906117d7565b1015610833578451633b9e9f0160e21b815233918101918252602082018d905291849183919082905f90829060400103925af1988915610503576107b1610810976107df956107bd947f36d2254ece9fe37664da4738f535058024f7b2ccb3d78abe69b705c1be2876ad9d610815575b505061032a61031a89611857565b6103536103438d61188a565b6001600160a01b0386165f908152600360205260409020610382908c90610240565b6107e982886118bd565b519384931696339684604091949392606082019560018060a01b0316825260208201520152565b0390a4005b8161082b92903d106104fc576104ed81836112d2565b505f806107a3565b845163185cfc6d60e11b8152fd5b6108589150873d89116104fc576104ed81836112d2565b5f6106e1565b50845163efda1a2760e01b8152fd5b6108849150853d87116104fc576104ed81836112d2565b5f610660565b505163673f032f60e11b8152fd5b806108a56108ab926112bf565b80610136565b5f6105d3565b60405163d92e233d60e01b8152600490fd5b6080906003190112610140576004356108db8161018a565b90602435906044359060643590565b34610140576108f8366108c3565b60055491939161091290610265906001600160a01b031681565b6040805163e0eb6af360e01b81523360048201526001600160a01b03851660248201526044810186905260648101879052909591602090829060849082905afa908115610503575f91610a6d575b5015610a5c576001600160a01b03831615610a4b578015610a3a57610a357fafda9316e64488bba379a6614bcee4516ef1793ee3844298c937b46b2cae5829939495610a106109ae8461188a565b6109f76109ba8761188a565b6109e76109c561130d565b6001600160a01b038c168152935f60208601526001600160801b031686850152565b6001600160801b03166060830152565b335f908152600360205260409020610382908a90610240565b51928392339684604091949392606082019560018060a01b0316825260208201520152565b0390a3005b8451636edcc52360e01b8152600490fd5b845163d92e233d60e01b8152600490fd5b8451634ca8886760e01b8152600490fd5b610a8f915060203d602011610a95575b610a8781836112d2565b8101906113a9565b5f610960565b503d610a7d565b34610140576040806003193601126101405760043590610abb8261018a565b60018060a01b038092165f526003602052805f206024355f5260205261043b815f20926001835194610aec8661129f565b80549283168652602086019260a01c83520154906001600160601b03610b5a610b4c610b3e6001600160801b03988987168982019781895260801c6060830152610b83575b516001600160a01b031690565b93516001600160601b031690565b93516001600160801b031690565b94516001600160a01b039092168252909116602082015292909116604083015281906060820190565b610b8c81611660565b610b31565b3461014057602036600319011261014057600435610bae8161018a565b610bb6611b3a565b6005546001600160a01b039182169181168214610c0a576001600160a01b03191681176005556040519081527f83292ae03f07801d2323041a63198dd4d11efb58fdd68f383a752b467c529f3790602090a1005b604051638c8728c760e01b8152600490fd5b34610140575f36600319011261014057610c34611b3a565b600280546001600160a01b03199081169091556001805491821690555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610140575f366003190112610140576002546001600160a01b033381831603610ceb576001600160601b0360a01b8092166002556001549133908316176001553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b60405163118cdaa760e01b8152336004820152602490fd5b34610140575f366003190112610140576001546040516001600160a01b039091168152602090f35b3461014057610d39366108c3565b610d5a836102408694959660018060a01b03165f52600360205260405f2090565b805490926001600160a01b0391821615610eb85760405163076b58b960e41b81523060048201526024810187905260448101869052606481018490529491169290606085608481875afa948515610503575f905f96610e83575b50600110610e7157833b156101405760405163434be96160e11b815260048101879052602481019190915260448101929092525f8260648183875af191821561050357610e2a92610e5e575b50610e0a84611857565b81546001600160a01b031660a09190911b6001600160a01b031916179055565b60405191825233917fda15728d9b7db891bd1235a1f54c14891973d2e88f4483636a7be928ccf5588c908060208101610810565b806108a5610e6b926112bf565b5f610e00565b604051630e3d8e8d60e11b8152600490fd5b60019650610ea9915060603d606011610eb1575b610ea181836112d2565b8101906113c1565b969050610db4565b503d610e97565b60405163673f032f60e11b8152600490fd5b34610140576040366003190112610140576004356001600160401b0381168082036101405760243590610efb611b3a565b80158015610fcb575b610fb957670de0b6b3a764000082818110928315610fa5575b505050610f93576005805467ffffffffffffffff60a01b191660a084901b67ffffffffffffffff60a01b161790557ff8333ae7adea4c8a83c7ed352346665b55517daecce9ddb81f555e9f6c96cd6b91610f7682600455565b604080516001600160401b039290921682526020820192909252a1005b60405163083887e960e21b8152600490fd5b610fb0929350611751565b115f8281610f1d565b60405163152b042360e21b8152600490fd5b50670de0b6b3a7640000811015610f04565b5f5b838110610fee5750505f910152565b8181015183820152602001610fdf565b9060209161101781518092818552858086019101610fdd565b601f01601f1916010190565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b8483106110585750505050505090565b9091929394958480611076600193603f198682030187528a51610ffe565b9801930193019194939290611048565b34610140576020366003190112610140576001600160401b036004358181116101405736602382011215610140578060040135918211610140573660248360051b830101116101405761043b9160246110df9201611570565b60405191829182611023565b34610140576110f936610530565b60405163057453a760e31b8152929391929091906001600160a01b03906020816004817f000000000000000000000000287d1e2a8de183a8bf8f2b09fa1340fbd766eb5986165afa80156105035782915f916111c4575b501633036111b257816108106111898686897ffebaeed78b2aaa8366a65cf2a811e7a20ce8c29f6563290cf5d4ece00379427897611951565b6040519384931696339684604091949392606082019560018060a01b0316825260208201520152565b604051634ca8886760e01b8152600490fd5b6111e6915060203d6020116111ec575b6111de81836112d2565b81019061161d565b5f611150565b503d6111d4565b34610140575f366003190112610140576002546040516001600160a01b039091168152602090f35b34610140576020366003190112610140576004356112388161018a565b611240611b3a565b600280546001600160a01b0319166001600160a01b039283169081179091556001549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b634e487b7160e01b5f52604160045260245ffd5b608081019081106001600160401b038211176112ba57604052565b61128b565b6001600160401b0381116112ba57604052565b90601f801991011681019081106001600160401b038211176112ba57604052565b90816020910312610140575190565b6040513d5f823e3d90fd5b6040519061131a8261129f565b565b906040516113298161129f565b82546001600160a01b038116825260a01c60208201526001909201546001600160801b038116604084015260801c6060830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160601b03918216908216039190821161138b57565b61135e565b6001600160801b03918216908216039190821161138b57565b90816020910312610140575180151581036101405790565b90816060910312610140578051916040602083015192015190565b6001600160401b0381116112ba5760051b60200190565b906113fd826113dc565b61140a60405191826112d2565b828152809261141b601f19916113dc565b01905f5b82811061142b57505050565b80606060208093850101520161141f565b634e487b7160e01b5f52603260045260245ffd5b91908110156114915760051b81013590601e19813603018212156101405701908135916001600160401b038311610140576020018236038113610140579190565b61143c565b908092918237015f815290565b6001600160401b0381116112ba57601f01601f191660200190565b3d156114e8573d906114cf826114a3565b916114dd60405193846112d2565b82523d5f602084013e565b606090565b602081830312610140578051906001600160401b038211610140570181601f8201121561014057805161151f816114a3565b9261152d60405194856112d2565b818452602082840101116101405761055d9160208085019101610fdd565b90602061055d928181520190610ffe565b80518210156114915760209160051b010190565b91909161157c836113f3565b925f5b81811061158b57505050565b5f80611598838587611450565b604093916115aa855180938193611496565b0390305af4906115b86114be565b91156115df5750906001916115cd828861155c565b526115d8818761155c565b500161157f565b90604481511061014057611619611604600492838101516024809183010191016114ed565b925162461bcd60e51b8152928392830161154b565b0390fd5b90816020910312610140575161055d8161018a565b6040513481527f09cea04c49f8b481a24e7cfff342f8b2a4ae27e595f0f3ba64ac8908efea5e0060203392a2565b60405163752a536d60e01b8152906020826004817f0000000000000000000000002a261e60fb14586b474c208b1b7ac6d0f50003066001600160a01b03165afa918215610503575f92611712575b5060608101906001600160801b0392836116cf84516001600160801b031690565b169182821461170b5761131a946103536117066103539585604061170696019461170086516001600160801b031690565b166117d7565b61188a565b5050505050565b61172c91925060203d6020116104fc576104ed81836112d2565b905f6116ae565b811561173d570490565b634e487b7160e01b5f52601260045260245ffd5b90808202905f19818409908280831092039180830392146117c657670de0b6b3a764000090828211156117b4577faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac10669940990828211900360ee1b910360121c170290565b60405163227bc15360e01b8152600490fd5b5050670de0b6b3a764000091500490565b9091828202915f198482099383808610950394808603951461184a57848311156117b457829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b50509061055d9250611733565b6001600160601b039081811161186b571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b6001600160801b039081811161189e571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b60025f54146119225760025f5581471061190a575f918291829182916001600160a01b03165af16118ec6114be565b50156118f85760015f55565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b90670de0b6b3a76400009182810292818404149015171561138b57565b92939290916001600160a01b03808216156108b1577f0000000000000000000000002a261e60fb14586b474c208b1b7ac6d0f50003061692833b15610140576040958651631d8557d760e01b81525f81600481838a5af1801561050357611b27575b506119d561024d836102408760018060a01b03165f52600360205260405f2090565b90878201926001600160801b036119f385516001600160801b031690565b1615611b1657611a0283611660565b88516303d1689d60e11b8152600481018390529560209081886024818c5afa978815610503575f98611af7575b50879a82860190611a4a61046a83516001600160601b031690565b8a11611ae75751633b9e9f0160e21b8152336004820152602481018690529983908b9060449082905f905af19687156105035761035361034361038297611706611ab09561131a9f8f61031a906104119f9b61032a936102409d611ac9575b5050611857565b6001600160a01b03165f90815260036020526040902090565b81611adf92903d106104fc576104ed81836112d2565b505f80611aa9565b5163efda1a2760e01b8152600490fd5b611b0f919850823d84116104fc576104ed81836112d2565b965f611a2f565b885163673f032f60e11b8152600490fd5b806108a5611b34926112bf565b5f6119b3565b6001546001600160a01b03163303610ceb5756fea26469706673582212207dd2347037e024c87551c91e253c373748a83703a673442ddffcf0f878f755ef64736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002a261e60fb14586b474c208b1b7ac6d0f5000306000000000000000000000000287d1e2a8de183a8bf8f2b09fa1340fbd766eb59000000000000000000000000144a98cb1cdbb23610501fe6108858d9b7d24934000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f00000000000000000000000000000000000000000000000000de0375f5d1f40000000000000000000000000000000000000000000000000000de0f48c233c4000
-----Decoded View---------------
Arg [0] : osTokenVaultController (address): 0x2A261e60FB14586B474C208b1B7AC6D0f5000306
Arg [1] : osTokenConfig (address): 0x287d1e2A8dE183A8bf8f2b09Fa1340fBd766eb59
Arg [2] : initialOwner (address): 0x144a98cb1CdBb23610501fE6108858D9B7D24934
Arg [3] : _authenticator (address): 0xFc8E3E7c919b4392D9F5B27015688e49c80015f0
Arg [4] : _liqThresholdPercent (uint64): 999860000000000000
Arg [5] : _liqBonusPercent (uint256): 1000068000000000000
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000002a261e60fb14586b474c208b1b7ac6d0f5000306
Arg [1] : 000000000000000000000000287d1e2a8de183a8bf8f2b09fa1340fbd766eb59
Arg [2] : 000000000000000000000000144a98cb1cdbb23610501fe6108858d9b7d24934
Arg [3] : 000000000000000000000000fc8e3e7c919b4392d9f5b27015688e49c80015f0
Arg [4] : 0000000000000000000000000000000000000000000000000de0375f5d1f4000
Arg [5] : 0000000000000000000000000000000000000000000000000de0f48c233c4000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.