Source Code
Overview
HYPE Balance
HYPE Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers.
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | ||||
|---|---|---|---|---|---|---|---|
| 25609101 | 53 mins ago | 0 HYPE | |||||
| 25606163 | 1 hr ago | 0 HYPE | |||||
| 25575581 | 10 hrs ago | 0 HYPE | |||||
| 25480856 | 35 hrs ago | 0 HYPE | |||||
| 25406575 | 2 days ago | 0 HYPE | |||||
| 25366537 | 2 days ago | 0 HYPE | |||||
| 25359010 | 2 days ago | 0 HYPE | |||||
| 25302943 | 3 days ago | 0 HYPE | |||||
| 25266008 | 3 days ago | 0 HYPE | |||||
| 25241643 | 4 days ago | 0 HYPE | |||||
| 25222212 | 4 days ago | 0 HYPE | |||||
| 25211901 | 4 days ago | 0 HYPE | |||||
| 25210101 | 4 days ago | 0 HYPE | |||||
| 25200249 | 4 days ago | 0 HYPE | |||||
| 25191920 | 4 days ago | 0 HYPE | |||||
| 25191920 | 4 days ago | 0 HYPE | |||||
| 25191900 | 4 days ago | 0 HYPE | |||||
| 25191900 | 4 days ago | 0 HYPE | |||||
| 25191794 | 4 days ago | 0 HYPE | |||||
| 25191794 | 4 days ago | 0 HYPE | |||||
| 25191660 | 4 days ago | 0 HYPE | |||||
| 25191660 | 4 days ago | 0 HYPE | |||||
| 25191641 | 4 days ago | 0 HYPE | |||||
| 25191641 | 4 days ago | 0 HYPE | |||||
| 25186543 | 4 days ago | 0 HYPE |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SingelTokenVirtualRewarderUpgradeable
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 2000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.19;
import {ISingelTokenVirtualRewarder} from "./interfaces/ISingelTokenVirtualRewarder.sol";
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import {VirtualRewarderCheckpoints} from "./libraries/VirtualRewarderCheckpoints.sol";
import {UpgradeCall} from "../integration/UpgradeCall.sol";
/**
* @title Single Token Virtual Rewarder Upgradeable
* @dev An upgradeable contract for managing token rewards based on virtual balances and epochs. It supports functionalities
* like deposits, withdrawals, and reward calculations based on checkpoints.
*/
contract SingelTokenVirtualRewarderUpgradeable is ISingelTokenVirtualRewarder, Initializable, UpgradeCall {
/**
* @title Struct for managing token information within a virtual reward system
* @notice Holds all pertinent data related to individual tokens within the reward system.
* @dev The structure stores balances, checkpoint indices, and a mapping of balance checkpoints.
*/
struct TokenInfo {
uint256 balance; // Current balance of the token
uint256 checkpointLastIndex; // Index of the last checkpoint for the token
uint256 lastEarnEpoch; // The last epoch during which rewards were calculated for the token
mapping(uint256 index => VirtualRewarderCheckpoints.Checkpoint) balanceCheckpoints; // Mapping of index to balance checkpoints
}
/**
* @notice Address of the strategy contract that interacts with this reward system
* @dev This should be set to the address of the strategy managing the tokens and their rewards.
*/
address public override strategy;
/**
* @notice Total supply of all tokens managed by the reward system
* @dev This total supply is used in reward calculations across different epochs.
*/
uint256 public override totalSupply;
/**
* @notice Index of the last checkpoint for the total supply
* @dev Used to track changes in total supply at each checkpoint.
*/
uint256 public totalSupplyCheckpointLastIndex;
/**
* @notice Mapping of total supply checkpoints
* @dev This stores checkpoints of the total supply which are referenced in reward calculations.
*/
mapping(uint256 index => VirtualRewarderCheckpoints.Checkpoint) public totalSupplyCheckpoints;
/**
* @notice Mapping from token ID to its associated TokenInfo
* @dev Keeps track of all relevant token information, including balances and checkpoints.
*/
mapping(uint256 tokenId => TokenInfo tokenInfo) public tokensInfo;
/**
* @notice Mapping from epoch to the total rewards allocated for that epoch
* @dev Used to determine the amount of rewards available per epoch, which influences reward calculations.
*/
mapping(uint256 epoch => uint256 rewards) public rewardsPerEpoch;
/**
* @notice Constant defining the length of a week in seconds
* @dev Used for time-related calculations, particularly in determining epoch boundaries.
*/
uint256 internal constant _WEEK = 86400 * 7;
/**
* @dev Custom error for unauthorized access attempts
* @notice Thrown when an operation is attempted by an unauthorized address, typically checked against the strategy.
*/
error AccessDenied();
/**
* @dev Custom error indicating operation involving zero amount which is not permitted
* @notice Used primarily in deposit, withdrawal, and reward distribution to prevent erroneous zero value transactions.
*/
error ZeroAmount();
error AddressZero();
/**
* @dev Modifier to restrict function calls to the strategy address
* @notice Ensures that only the designated strategy can call certain functions.
*/
modifier onlyStrategy() {
if (msg.sender != strategy) {
revert AccessDenied();
}
_;
}
/**
* @dev Constructor that disables initialization on implementation.
*/
constructor() {
_disableInitializers();
}
/**
* @notice Initializes the contract with necessary governance and operational addresses
* @dev Sets up operational aspects of the contract. This function can only be called once.
*
* @param strategy_ The strategy address that will interact with this contract
*/
function initialize(address strategy_) external override initializer {
_checkAddressZero(strategy_);
strategy = strategy_;
}
/**
* @notice Deposits a specific amount of tokens for a given tokenId
* @dev This function updates the token's balance and total supply and writes a new checkpoint.
*
* @param tokenId_ The ID of the token to deposit
* @param amount_ The amount of tokens to deposit
*/
function deposit(uint256 tokenId_, uint256 amount_) external onlyStrategy {
if (amount_ == 0) {
revert ZeroAmount();
}
TokenInfo storage info = tokensInfo[tokenId_];
info.balance += amount_;
totalSupply += amount_;
uint256 currentEpoch = _currentEpoch();
_writeCheckpoints(info, currentEpoch);
emit Deposit(tokenId_, amount_, currentEpoch);
}
/**
* @notice Withdraws a specific amount of tokens for a given tokenId
* @dev This function updates the token's balance and total supply and writes a new checkpoint.
*
* @param tokenId_ The ID of the token from which to withdraw
* @param amount_ The amount of tokens to withdraw
*/
function withdraw(uint256 tokenId_, uint256 amount_) external onlyStrategy {
TokenInfo storage info = tokensInfo[tokenId_];
if (info.balance == 0 || amount_ == 0) {
revert ZeroAmount();
}
info.balance -= amount_;
totalSupply -= amount_;
uint256 currentEpoch = _currentEpoch();
_writeCheckpoints(info, currentEpoch);
emit Withdraw(tokenId_, amount_, currentEpoch);
}
/**
* @notice Harvests rewards for a specific tokenId
* @dev Calculates the available rewards for the token and updates the last earned epoch.
*
* IMPORTANT: If the reward was issued after the harvest summon in an epoch,
* you will not be able to claim it. Wait for the distribution of rewards for the past era
*
* @param tokenId_ The ID of the token for which to harvest rewards
* @return reward The amount of rewards harvested
*/
function harvest(uint256 tokenId_) external onlyStrategy returns (uint256 reward) {
reward = _calculateAvailableRewardsAmount(tokenId_);
uint256 currentEpoch = _currentEpoch();
tokensInfo[tokenId_].lastEarnEpoch = currentEpoch;
emit Harvest(tokenId_, reward, currentEpoch);
return reward;
}
/**
* @notice Notifies the contract of a new reward amount to be distributed in the current epoch
* @dev Updates the rewards for the current epoch and emits a notification event.
*
* @param amount_ The amount of rewards to distribute
*/
function notifyRewardAmount(uint256 amount_) external onlyStrategy {
if (amount_ == 0) {
revert ZeroAmount();
}
uint256 currentEpoch = _currentEpoch();
rewardsPerEpoch[currentEpoch] += amount_;
emit NotifyReward(amount_, currentEpoch);
}
/**
* @notice Calculates the available rewards amount for a given tokenId
*
* @param tokenId_ The ID of the token to calculate rewards for
* @return reward The calculated reward amount
*/
function calculateAvailableRewardsAmount(uint256 tokenId_) external view returns (uint256 reward) {
return _calculateAvailableRewardsAmount(tokenId_);
}
/**
* @notice Provides the current balance of a specific tokenId
*
* @param tokenId_ The ID of the token to check
* @return The current balance of the token
*/
function balanceOf(uint256 tokenId_) external view returns (uint256) {
return tokensInfo[tokenId_].balance;
}
/**
* @notice Provides the balance of a specific tokenId at a given timestamp
*
* @param tokenId_ The ID of the token to check
* @param timestamp_ The specific timestamp to check the balance at
* @return The balance of the token at the given timestamp
*/
function balanceOfAt(uint256 tokenId_, uint256 timestamp_) external view returns (uint256) {
return
VirtualRewarderCheckpoints.getAmount(
tokensInfo[tokenId_].balanceCheckpoints,
tokensInfo[tokenId_].checkpointLastIndex,
timestamp_
);
}
/**
* @notice Provides the total supply of tokens at a given timestamp
*
* @param timestamp_ The timestamp to check the total supply at
* @return The total supply of tokens at the specified timestamp
*/
function totalSupplyAt(uint256 timestamp_) external view returns (uint256) {
return VirtualRewarderCheckpoints.getAmount(totalSupplyCheckpoints, totalSupplyCheckpointLastIndex, timestamp_);
}
/**
* @notice Returns the checkpoint data for a specific token and index
*
* @param tokenId_ The ID of the token to check
* @param index The index of the checkpoint to retrieve
* @return A checkpoint struct containing the timestamp and amount at that index
*/
function balanceCheckpoints(uint256 tokenId_, uint256 index) external view returns (VirtualRewarderCheckpoints.Checkpoint memory) {
return tokensInfo[tokenId_].balanceCheckpoints[index];
}
/**
* @dev Writes checkpoints for token balance and total supply at a given epoch.
* @notice This function updates both the token's individual balance checkpoint and the total supply checkpoint.
*
* @param info_ The storage reference to the token's information which includes balance and checkpoint index.
* @param epoch_ The epoch for which the checkpoint is being written.
*/
function _writeCheckpoints(TokenInfo storage info_, uint256 epoch_) internal {
info_.checkpointLastIndex = VirtualRewarderCheckpoints.writeCheckpoint(
info_.balanceCheckpoints,
info_.checkpointLastIndex,
epoch_,
info_.balance
);
totalSupplyCheckpointLastIndex = VirtualRewarderCheckpoints.writeCheckpoint(
totalSupplyCheckpoints,
totalSupplyCheckpointLastIndex,
epoch_,
totalSupply
);
}
/**
* @notice This function accumulates rewards over each epoch since last claimed to present.
* @dev Calculates the total available rewards for a given tokenId since the last earned epoch.
*
* @param tokenId_ The identifier of the token for which rewards are being calculated.
* @return reward The total accumulated reward since the last claim.
*/
function _calculateAvailableRewardsAmount(uint256 tokenId_) internal view returns (uint256 reward) {
uint256 checkpointLastIndex = tokensInfo[tokenId_].checkpointLastIndex;
if (checkpointLastIndex == 0) {
return 0;
}
uint256 startEpoch = tokensInfo[tokenId_].lastEarnEpoch;
uint256 index = startEpoch == 0
? 1
: VirtualRewarderCheckpoints.getCheckpointIndex(
tokensInfo[tokenId_].balanceCheckpoints,
tokensInfo[tokenId_].checkpointLastIndex,
startEpoch
);
uint256 epochTimestamp = tokensInfo[tokenId_].balanceCheckpoints[index].timestamp;
if (epochTimestamp > startEpoch) {
startEpoch = epochTimestamp;
}
uint256 currentEpoch = _currentEpoch();
uint256 notHarvestedEpochCount = (currentEpoch - startEpoch) / _WEEK;
for (uint256 i; i < notHarvestedEpochCount; ) {
reward += _calculateRewardPerEpoch(tokenId_, startEpoch);
startEpoch += _WEEK;
unchecked {
i++;
}
}
}
/**
* @notice This method uses the reward per epoch and the token's proportion of the total supply to determine the reward amount.
* @dev Calculates the reward for a specific tokenId for a single epoch based on the token's balance and total supply.
*
* @param tokenId_ The identifier of the token.
* @param epoch_ The epoch for which to calculate the reward.
* @return The calculated reward for the epoch.
*/
function _calculateRewardPerEpoch(uint256 tokenId_, uint256 epoch_) internal view returns (uint256) {
uint256 balance = VirtualRewarderCheckpoints.getAmount(
tokensInfo[tokenId_].balanceCheckpoints,
tokensInfo[tokenId_].checkpointLastIndex,
epoch_
);
uint256 supply = VirtualRewarderCheckpoints.getAmount(totalSupplyCheckpoints, totalSupplyCheckpointLastIndex, epoch_);
if (supply == 0) {
return 0;
}
return (balance * rewardsPerEpoch[epoch_ + _WEEK]) / supply;
}
/**
* @notice This function return current epoch
* @dev Retrieves the current epoch
*
* @return The current epoch
*/
function _currentEpoch() internal view returns (uint256) {
return _roundToEpoch(block.timestamp);
}
/**
* @notice This function is used to align timestamps with epoch boundaries.
* @dev Rounds down the timestamp to the start of the epoch.
*
* @param timestamp_ The timestamp to round down.
* @return The timestamp rounded down to the nearest epoch start.
*/
function _roundToEpoch(uint256 timestamp_) internal pure returns (uint256) {
return (timestamp_ / _WEEK) * _WEEK;
}
/**
* @dev Checked provided address on zero value, throw AddressZero error in case when addr_ is zero
*
* @param addr_ The address which will checked on zero
*/
function _checkAddressZero(address addr_) internal pure {
if (addr_ == address(0)) {
revert AddressZero();
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/Address.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IUpgradeCall {
function upgradeCall() external;
}// SPDX-License-Identifier: MIT
pragma solidity =0.8.19;
import {IUpgradeCall} from "./interfaces/IUgradeCall.sol";
abstract contract UpgradeCall is IUpgradeCall {
function upgradeCall() external virtual override {}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
/**
* @title Interface for Single Token Virtual Rewarder
* @dev Defines the basic interface for a reward system that handles deposits, withdrawals, and rewards based on token staking over different epochs.
*/
interface ISingelTokenVirtualRewarder {
/**
* @dev Emitted when a deposit is made.
* @param tokenId The identifier of the token being deposited.
* @param amount The amount of tokens deposited.
* @param epoch The epoch during which the deposit occurs.
*/
event Deposit(uint256 indexed tokenId, uint256 indexed amount, uint256 indexed epoch);
/**
* @dev Emitted when a withdrawal is made.
* @param tokenId The identifier of the token being withdrawn.
* @param amount The amount of tokens withdrawn.
* @param epoch The epoch during which the withdrawal occurs.
*/
event Withdraw(uint256 indexed tokenId, uint256 indexed amount, uint256 indexed epoch);
/**
* @dev Emitted when rewards are harvested.
* @param tokenId The identifier of the token for which rewards are harvested.
* @param rewardAmount The amount of rewards harvested.
* @param epochCount The epoch during which the harvest occurs.
*/
event Harvest(uint256 indexed tokenId, uint256 indexed rewardAmount, uint256 indexed epochCount);
/**
* @dev Emitted when a new reward amount is notified to be added to the pool.
* @param rewardAmount The amount of rewards added.
* @param epoch The epoch during which the reward is added.
*/
event NotifyReward(uint256 indexed rewardAmount, uint256 indexed epoch);
/**
* @notice Handles the deposit of tokens into the reward system.
* @param tokenId The identifier of the token being deposited.
* @param amount The amount of tokens to deposit.
*/
function deposit(uint256 tokenId, uint256 amount) external;
/**
* @notice Handles the withdrawal of tokens from the reward system.
* @param tokenId The identifier of the token being withdrawn.
* @param amount The amount of tokens to withdraw.
*/
function withdraw(uint256 tokenId, uint256 amount) external;
/**
* @notice Notifies the system of a new reward amount to be distributed.
* @param amount The amount of the new reward to add.
*/
function notifyRewardAmount(uint256 amount) external;
/**
* @notice Harvests rewards for a specific token.
* @param tokenId The identifier of the token for which to harvest rewards.
* @return reward The amount of harvested rewards.
*/
function harvest(uint256 tokenId) external returns (uint256 reward);
/**
* @notice Calculates the available amount of rewards for a specific token.
* @param tokenId The identifier of the token.
* @return reward The calculated reward amount.
*/
function calculateAvailableRewardsAmount(uint256 tokenId) external view returns (uint256 reward);
/**
* @notice Returns the strategy address associated with this contract.
* @return The address of the strategy.
*/
function strategy() external view returns (address);
/**
* @notice Returns the total supply of tokens under management.
* @return The total supply of tokens.
*/
function totalSupply() external view returns (uint256);
/**
* @notice Returns the balance of a specific token.
* @param tokenId The identifier of the token.
* @return The balance of the specified token.
*/
function balanceOf(uint256 tokenId) external view returns (uint256);
/**
* @notice Provides the balance of a specific tokenId at a given timestamp
*
* @param tokenId_ The ID of the token to check
* @param timestamp_ The specific timestamp to check the balance at
* @return The balance of the token at the given timestamp
*/
function balanceOfAt(uint256 tokenId_, uint256 timestamp_) external view returns (uint256);
/**
* @notice Provides the total supply of tokens at a given timestamp
*
* @param timestamp_ The timestamp to check the total supply at
* @return The total supply of tokens at the specified timestamp
*/
function totalSupplyAt(uint256 timestamp_) external view returns (uint256);
/**
* @notice Returns the reward per epoch for a specific epoch.
* @param epoch The epoch for which to retrieve the reward amount.
* @return The reward amount for the specified epoch.
*/
function rewardsPerEpoch(uint256 epoch) external view returns (uint256);
/**
* @notice Initializes the contract with necessary governance and operational addresses
* @dev Sets up operational aspects of the contract. This function can only be called once.
*
* @param strategy_ The strategy address that will interact with this contract
*/
function initialize(address strategy_) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.19;
/**
* @title VirtualRewarderCheckpoints
* @dev Library to manage checkpoints in a virtual reward system. This library facilitates the storage of state
* at specific timestamps for historical data tracking and reward calculation.
*/
library VirtualRewarderCheckpoints {
struct Checkpoint {
uint256 timestamp; // Timestamp at which the checkpoint is logged
uint256 amount; // Amount or value associated with the checkpoint
}
/**
* @notice Writes a new checkpoint or updates an existing one in the mapping.
* @dev If a checkpoint at the given timestamp already exists, it updates the amount; otherwise, it creates a new checkpoint.
*
* @param self_ Mapping from index to Checkpoint.
* @param lastIndex_ Index of the last recorded checkpoint.
* @param timestamp_ Timestamp for the new checkpoint.
* @param amount_ Amount to be associated with the new checkpoint.
* @return newIndex The index of the newly written checkpoint.
*
* Example:
* mapping(uint256 => Checkpoint) checkpoints;
* uint256 lastIndex = 0;
* lastIndex = VirtualRewarderCheckpoints.writeCheckpoint(checkpoints, lastIndex, block.timestamp, 100);
*/
function writeCheckpoint(
mapping(uint256 index => Checkpoint checkpoint) storage self_,
uint256 lastIndex_,
uint256 timestamp_,
uint256 amount_
) internal returns (uint256 newIndex) {
Checkpoint memory last = self_[lastIndex_];
newIndex = last.timestamp == timestamp_ ? lastIndex_ : lastIndex_ + 1;
self_[newIndex] = Checkpoint({timestamp: timestamp_, amount: amount_});
}
/**
* @notice Retrieves the amount at the checkpoint closest to and not after the given timestamp.
*
* @param self_ Mapping from index to Checkpoint.
* @param lastIndex_ Index of the last checkpoint.
* @param timestamp_ Timestamp for querying the amount.
* @return amount The amount at the closest checkpoint.
*
* Example:
* uint256 amount = VirtualRewarderCheckpoints.getAmount(checkpoints, lastIndex, block.timestamp);
*/
function getAmount(
mapping(uint256 index => Checkpoint checkpoint) storage self_,
uint256 lastIndex_,
uint256 timestamp_
) internal view returns (uint256) {
return self_[getCheckpointIndex(self_, lastIndex_, timestamp_)].amount;
}
/**
* @notice Retrieves the index of the checkpoint that is nearest to and less than or equal to the given timestamp.
* @dev Performs a binary search to find the closest timestamp, which is efficient on sorted data.
*
* @param self_ Mapping from index to Checkpoint.
* @param lastIndex_ Index of the last checkpoint.
* @param timestamp_ Timestamp to query the nearest checkpoint for.
* @return index The index of the closest checkpoint by timestamp.
*
* Example:
* uint256 index = VirtualRewarderCheckpoints.getCheckpointIndex(checkpoints, lastIndex, block.timestamp - 10);
*/
function getCheckpointIndex(
mapping(uint256 index => Checkpoint checkpoint) storage self_,
uint256 lastIndex_,
uint256 timestamp_
) internal view returns (uint256) {
if (lastIndex_ == 0) {
return 0;
}
if (self_[lastIndex_].timestamp <= timestamp_) {
return lastIndex_;
}
if (self_[0].timestamp > timestamp_) {
return 0;
}
uint256 start;
uint256 end = lastIndex_;
while (end > start) {
uint256 middle = end - (end - start) / 2;
Checkpoint memory checkpoint = self_[middle];
if (checkpoint.timestamp == timestamp_) {
return middle;
} else if (checkpoint.timestamp < timestamp_) {
start = middle;
} else {
end = middle - 1;
}
}
return start;
}
}{
"evmVersion": "paris",
"viaIR": true,
"optimizer": {
"enabled": true,
"runs": 2000
},
"metadata": {
"bytecodeHash": "none"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessDenied","type":"error"},{"inputs":[],"name":"AddressZero","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"epochCount","type":"uint256"}],"name":"Harvest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"NotifyReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"balanceCheckpoints","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct VirtualRewarderCheckpoints.Checkpoint","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"timestamp_","type":"uint256"}],"name":"balanceOfAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"calculateAvailableRewardsAmount","outputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"harvest","outputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"strategy_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"rewardsPerEpoch","outputs":[{"internalType":"uint256","name":"rewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokensInfo","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"checkpointLastIndex","type":"uint256"},{"internalType":"uint256","name":"lastEarnEpoch","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp_","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyCheckpointLastIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"totalSupplyCheckpoints","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"upgradeCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608080604052346100c1576000549060ff8260081c1661006f575060ff80821603610034575b604051610d0b90816100c78239f35b60ff90811916176000557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160ff8152a138610025565b62461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b6064820152608490fd5b600080fdfe608060408181526004908136101561001657600080fd5b600092833560e01c90816318160ddd146107d2575080633bb2fad9146107be5780633c6b16ab1461071c578063441a3e701461065c5780635c5f6c3d1461063d57806363db9f331461061a57806369448b6d146105dd57806371e1a8ac14610580578063853c8aeb1461054c57806394cee7b314610524578063981b24d0146104ee5780639cc7f708146104c7578063a8c62e7614610491578063b66e4cdf1461045f578063c4d66de814610231578063ddc63262146101965763e2bbb158146100df57600080fd5b34610192576100ed366107ee565b91909273ffffffffffffffffffffffffffffffffffffffff855460101c1633036101845782156101765783855260205283209161012b828454610809565b835561013982600154610809565b60015561014f61014842610afe565b809461086f565b7f33da4f9b82b3e18a281ca2cabbe2f076925692abb593b7ea3f850009e8ec97708480a480f35b9051631f2a200560e01b8152fd5b9051634ca8886760e01b8152fd5b8280fd5b5082903461022d57602060031936011261022d57823573ffffffffffffffffffffffffffffffffffffffff835460101c16330361021e57927f4ec2d4038813a7f233af1d6d09519189db3ed5bc5b823bf72f6d3144574721de91846101fc602096610979565b93849261020842610afe565b9483885288528460028289200155519580a48152f35b838251634ca8886760e01b8152fd5b5080fd5b50346101925760206003193601126101925781359073ffffffffffffffffffffffffffffffffffffffff82169283830361045b5784549360ff8560081c16159485809661044e575b8015610437575b156103b4578560017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008316178855610386575b501561035f575075ffffffffffffffffffffffffffffffffffffffff000084549260101b1692837fffffffffffffffffffff0000000000000000000000000000000000000000ffff8416178555610308578380f35b7f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498927fffffffffffffffffffff000000000000000000000000000000000000000000ff602093161784555160018152a13880808380f35b90517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016610101178655386102b3565b60848360208651917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152fd5b50303b1580156102805750600160ff821614610280565b50600160ff821610610279565b8480fd5b509034610192576020600319360112610192579181923581526003602052206001815491015482519182526020820152f35b83823461022d578160031936011261022d5773ffffffffffffffffffffffffffffffffffffffff6020925460101c169051908152f35b50903461019257602060031936011261019257602092818392358252845220549051908152f35b509034610192576020600319360112610192578160209361051460019335600254610b35565b8152600385522001549051908152f35b5090346101925760206003193601126101925760209282913581526005845220549051908152f35b509034610192576105799082602094610564366107ee565b93908252865220600360018201549101610b18565b9051908152f35b50903461019257918192610593366107ee565b91908360206105a0610839565b82815201528352602052600383832001908252602052206105bf610839565b60206001835493848452015491019081528251918252516020820152f35b5090346101925760206003193601126101925760609281839235825260205220805491600260018301549201549181519384526020840152820152f35b50823461063a57602060031936011261063a575061057960209235610979565b80fd5b83823461022d578160031936011261022d576020906002549051908152f35b50346101925761066b366107ee565b9173ffffffffffffffffffffffffffffffffffffffff855460101c16330361070d57818552836020528085209384549182158015610705575b6106f8575050826106b49161082c565b83556106c28260015461082c565b6001556106d161014842610afe565b7fa01a72713bf837059e3a668d28f0de277fb7f24f2a4e95bf926703c95b5f12b28480a480f35b51631f2a200560e01b8152fd5b5084156106a4565b839051634ca8886760e01b8152fd5b5090346101925760206003193601126101925780359073ffffffffffffffffffffffffffffffffffffffff845460101c1633036107b05781156107a2575061076342610afe565b9182845260056020528320610779828254610809565b90557f0364fe27a9346f7a558ebdc4ce9cc58896d295d9db8b28960680ec6b0db571c98380a380f35b8251631f2a200560e01b8152fd5b8251634ca8886760e01b8152fd5b833461063a578060031936011261063a5780f35b84903461022d578160031936011261022d576020906001548152f35b6003196040910112610804576004359060243590565b600080fd5b9190820180921161081657565b634e487b7160e01b600052601160045260246000fd5b9190820391821161081657565b604051906040820182811067ffffffffffffffff82111761085957604052565b634e487b7160e01b600052604160045260246000fd5b90600382016001908184018054945490600092868452846020978289528760408720610899610839565b815480825291850154908c01520361095357935b6108b5610839565b92888452898401918252858752895260408620925183555191015555600254908254918082526003865284604083206108ec610839565b815480825291870154908901520361092957906003604092965b61090e610839565b96875280870194855287835252209251835551910155600255565b83810180911161093f5790600360409296610906565b602482634e487b7160e01b81526011600452fd5b908101809111610965578590936108ad565b602485634e487b7160e01b81526011600452fd5b9060009160009080825260049182602052604081209060019384830154928315610a6757600281015480948115600014610a5657505050845b84835281602052600360408420019083526020526040822054838111610a4e575b509193929062093a8092836109f0876109eb42610afe565b61082c565b049382935b858510610a06575050505050505050565b9091929394959698610a2290610a1c8b84610a71565b90610809565b98828101809111610a3b579695948601939291906109f5565b602485601186634e487b7160e01b835252fd5b9250386109d3565b6003610a629301610c13565b6109b2565b5090955050505050565b60009081526004602052610a918260408320600360018201549101610b18565b90610a9e83600254610b35565b815260036020526001604082200154928315610af75762093a80810180911161093f5781526005602052604081205491828102928184041490151715610ae357500490565b80634e487b7160e01b602492526011600452fd5b5091505090565b62093a808091048181029181830414901517156108165790565b91610b239183610c13565b60005260205260016040600020015490565b908115610c0c5760008281526003916020838152604082818520541115610c0457838052828185205411610bfb579392919082955b868111610b7a5750505050505090565b610b84878261082c565b96610b93600198891c8361082c565b978886528684528786209084610ba7610839565b918354938484520154910152848114600014610bc857505050505050505090565b93809596979892939410600014610be65750955b9493929190610b6a565b96915060001981019081116109655790610bdc565b50505091505090565b505050505090565b5050600090565b90918215610cf657600083815260209183835260409281848420541115610c0457828052818484205411610ced57939291908195945b868611610c595750505050505090565b610c63878761082c565b96610c72600198891c8861082c565b80988186528784528686209084610c87610839565b918354938484520154910152848114600014610ca95750505050505050505090565b93809596979899939410600014610cc8575050955b9493929190610c49565b90975060001981019150811115610cbe57602484634e487b7160e01b81526011600452fd5b50509250505090565b50505060009056fea164736f6c6343000813000a
Deployed Bytecode
0x608060408181526004908136101561001657600080fd5b600092833560e01c90816318160ddd146107d2575080633bb2fad9146107be5780633c6b16ab1461071c578063441a3e701461065c5780635c5f6c3d1461063d57806363db9f331461061a57806369448b6d146105dd57806371e1a8ac14610580578063853c8aeb1461054c57806394cee7b314610524578063981b24d0146104ee5780639cc7f708146104c7578063a8c62e7614610491578063b66e4cdf1461045f578063c4d66de814610231578063ddc63262146101965763e2bbb158146100df57600080fd5b34610192576100ed366107ee565b91909273ffffffffffffffffffffffffffffffffffffffff855460101c1633036101845782156101765783855260205283209161012b828454610809565b835561013982600154610809565b60015561014f61014842610afe565b809461086f565b7f33da4f9b82b3e18a281ca2cabbe2f076925692abb593b7ea3f850009e8ec97708480a480f35b9051631f2a200560e01b8152fd5b9051634ca8886760e01b8152fd5b8280fd5b5082903461022d57602060031936011261022d57823573ffffffffffffffffffffffffffffffffffffffff835460101c16330361021e57927f4ec2d4038813a7f233af1d6d09519189db3ed5bc5b823bf72f6d3144574721de91846101fc602096610979565b93849261020842610afe565b9483885288528460028289200155519580a48152f35b838251634ca8886760e01b8152fd5b5080fd5b50346101925760206003193601126101925781359073ffffffffffffffffffffffffffffffffffffffff82169283830361045b5784549360ff8560081c16159485809661044e575b8015610437575b156103b4578560017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008316178855610386575b501561035f575075ffffffffffffffffffffffffffffffffffffffff000084549260101b1692837fffffffffffffffffffff0000000000000000000000000000000000000000ffff8416178555610308578380f35b7f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498927fffffffffffffffffffff000000000000000000000000000000000000000000ff602093161784555160018152a13880808380f35b90517f9fabe1c1000000000000000000000000000000000000000000000000000000008152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016610101178655386102b3565b60848360208651917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152fd5b50303b1580156102805750600160ff821614610280565b50600160ff821610610279565b8480fd5b509034610192576020600319360112610192579181923581526003602052206001815491015482519182526020820152f35b83823461022d578160031936011261022d5773ffffffffffffffffffffffffffffffffffffffff6020925460101c169051908152f35b50903461019257602060031936011261019257602092818392358252845220549051908152f35b509034610192576020600319360112610192578160209361051460019335600254610b35565b8152600385522001549051908152f35b5090346101925760206003193601126101925760209282913581526005845220549051908152f35b509034610192576105799082602094610564366107ee565b93908252865220600360018201549101610b18565b9051908152f35b50903461019257918192610593366107ee565b91908360206105a0610839565b82815201528352602052600383832001908252602052206105bf610839565b60206001835493848452015491019081528251918252516020820152f35b5090346101925760206003193601126101925760609281839235825260205220805491600260018301549201549181519384526020840152820152f35b50823461063a57602060031936011261063a575061057960209235610979565b80fd5b83823461022d578160031936011261022d576020906002549051908152f35b50346101925761066b366107ee565b9173ffffffffffffffffffffffffffffffffffffffff855460101c16330361070d57818552836020528085209384549182158015610705575b6106f8575050826106b49161082c565b83556106c28260015461082c565b6001556106d161014842610afe565b7fa01a72713bf837059e3a668d28f0de277fb7f24f2a4e95bf926703c95b5f12b28480a480f35b51631f2a200560e01b8152fd5b5084156106a4565b839051634ca8886760e01b8152fd5b5090346101925760206003193601126101925780359073ffffffffffffffffffffffffffffffffffffffff845460101c1633036107b05781156107a2575061076342610afe565b9182845260056020528320610779828254610809565b90557f0364fe27a9346f7a558ebdc4ce9cc58896d295d9db8b28960680ec6b0db571c98380a380f35b8251631f2a200560e01b8152fd5b8251634ca8886760e01b8152fd5b833461063a578060031936011261063a5780f35b84903461022d578160031936011261022d576020906001548152f35b6003196040910112610804576004359060243590565b600080fd5b9190820180921161081657565b634e487b7160e01b600052601160045260246000fd5b9190820391821161081657565b604051906040820182811067ffffffffffffffff82111761085957604052565b634e487b7160e01b600052604160045260246000fd5b90600382016001908184018054945490600092868452846020978289528760408720610899610839565b815480825291850154908c01520361095357935b6108b5610839565b92888452898401918252858752895260408620925183555191015555600254908254918082526003865284604083206108ec610839565b815480825291870154908901520361092957906003604092965b61090e610839565b96875280870194855287835252209251835551910155600255565b83810180911161093f5790600360409296610906565b602482634e487b7160e01b81526011600452fd5b908101809111610965578590936108ad565b602485634e487b7160e01b81526011600452fd5b9060009160009080825260049182602052604081209060019384830154928315610a6757600281015480948115600014610a5657505050845b84835281602052600360408420019083526020526040822054838111610a4e575b509193929062093a8092836109f0876109eb42610afe565b61082c565b049382935b858510610a06575050505050505050565b9091929394959698610a2290610a1c8b84610a71565b90610809565b98828101809111610a3b579695948601939291906109f5565b602485601186634e487b7160e01b835252fd5b9250386109d3565b6003610a629301610c13565b6109b2565b5090955050505050565b60009081526004602052610a918260408320600360018201549101610b18565b90610a9e83600254610b35565b815260036020526001604082200154928315610af75762093a80810180911161093f5781526005602052604081205491828102928184041490151715610ae357500490565b80634e487b7160e01b602492526011600452fd5b5091505090565b62093a808091048181029181830414901517156108165790565b91610b239183610c13565b60005260205260016040600020015490565b908115610c0c5760008281526003916020838152604082818520541115610c0457838052828185205411610bfb579392919082955b868111610b7a5750505050505090565b610b84878261082c565b96610b93600198891c8361082c565b978886528684528786209084610ba7610839565b918354938484520154910152848114600014610bc857505050505050505090565b93809596979892939410600014610be65750955b9493929190610b6a565b96915060001981019081116109655790610bdc565b50505091505090565b505050505090565b5050600090565b90918215610cf657600083815260209183835260409281848420541115610c0457828052818484205411610ced57939291908195945b868611610c595750505050505090565b610c63878761082c565b96610c72600198891c8861082c565b80988186528784528686209084610c87610839565b918354938484520154910152848114600014610ca95750505050505050505090565b93809596979899939410600014610cc8575050955b9493929190610c49565b90975060001981019150811115610cbe57602484634e487b7160e01b81526011600452fd5b50509250505090565b50505060009056fea164736f6c6343000813000a
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in HYPE
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.