Source Code
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TransferRewardNotifier
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.23;
import {INotifiableRewardReceiver, IERC20} from "../interfaces/INotifiableRewardReceiver.sol";
import {RewardTokenNotifierBase} from "../notifiers/RewardTokenNotifierBase.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/// @title TransferRewardNotifier
/// @author [ScopeLift](https://scopelift.co)
/// @notice A reward notifier that uses ERC20 transfer to move reward tokens from this contract's
/// balance to the Staker contract. This implementation is suitable when reward tokens are held
/// directly by the notifier contract itself, rather than being transferred from a separate source.
///
/// The contract allows the owner to configure the reward parameters (amount and interval). The
/// contract must maintain a sufficient balance of reward tokens for distributions to succeed.
contract TransferRewardNotifier is RewardTokenNotifierBase {
using SafeERC20 for IERC20;
/// @param _receiver The contract that will receive reward notifications, typically an instance
/// of Staker.
/// @param _initialRewardAmount The initial amount of reward tokens to be distributed per
/// notification.
/// @param _initialRewardInterval The initial minimum time that must elapse between
/// notifications.
/// @param _initialOwner The address that will have permission to update contract parameters.
constructor(
INotifiableRewardReceiver _receiver,
uint256 _initialRewardAmount,
uint256 _initialRewardInterval,
address _initialOwner
)
RewardTokenNotifierBase(_receiver, _initialRewardAmount, _initialRewardInterval)
Ownable(_initialOwner)
{}
/// @notice Approves an address to transferFrom tokens held by this contract.
/// @param _spender The address to approve for token spending.
/// @param _amount The amount of tokens to approve.
/// @dev Caller must be the contract owner. This enables tokens to be clawed back to end rewards
/// as desired.
function approve(address _spender, uint256 _amount) external {
_checkOwner();
TOKEN.safeIncreaseAllowance(_spender, _amount);
}
/// @inheritdoc RewardTokenNotifierBase
/// @dev Transfers exactly rewardAmount tokens from this contract's balance to the receiver
/// using transfer. This contract must have a sufficient balance of reward tokens for the
/// transfer to succeed.
function _sendTokensToReceiver() internal virtual override {
TOKEN.safeTransfer(address(RECEIVER), rewardAmount);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.23;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title INotifiableRewardReceiver
/// @author [ScopeLift](https://scopelift.co)
/// @notice The communication interface between contracts that distribute rewards and the
/// Staker contract. In particular, said contracts only need to know the staker
/// implements the specified methods in order to forward payouts to the staker contract. The
/// Staker contract receives the rewards and abstracts the distribution mechanics.
interface INotifiableRewardReceiver {
/// @notice ERC20 token in which rewards are denominated and distributed.
function REWARD_TOKEN() external view returns (IERC20);
/// @notice Method called to notify a reward receiver it has received a reward.
/// @param _amount The amount of reward.
function notifyRewardAmount(uint256 _amount) external;
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.23;
import {INotifiableRewardReceiver, IERC20} from "../interfaces/INotifiableRewardReceiver.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
/// @title RewardTokenNotifierBase
/// @author [ScopeLift](https://scopelift.co)
/// @notice An abstract reward notifier contract for managing the distribution of rewards to Staker
/// instances.
///
/// Specifically, this base contract manages the details of directly distributing tokens
/// of the same type as the reward token. In other words, value does not need to be converted in
/// any way from one type of token to the reward token, rather reward tokens are simply moved to
/// Staker instance.
///
/// The contract is not opinionated about how the tokens are "moved" to the notifier. Inheriting
/// contracts must implement the `_sendTokensToReceiver` method to effectuate the movement of the
/// reward tokens using whatever mechanic is desired. The implementation must ensure that exactly
/// rewardAmount tokens are moved to the receiver.
///
/// The contract enforces a minimum interval between reward notifications. The contract ensures
/// that a set amount of reward tokens are distributed each time. These parameters are updatable by
/// the contract owner, which will presumably be the DAO itself in most instances.
abstract contract RewardTokenNotifierBase is Ownable {
/// @notice Emitted when the reward amount is changed.
/// @param oldRewardAmount The previous reward amount.
/// @param newRewardAmount The new reward amount.
event RewardAmountSet(uint256 oldRewardAmount, uint256 newRewardAmount);
/// @notice Emitted when the reward interval is changed.
/// @param oldRewardAmount The previous reward interval duration.
/// @param newRewardAmount The new reward interval duration.
event RewardIntervalSet(uint256 oldRewardAmount, uint256 newRewardAmount);
/// @notice Emitted when rewards are distributed to the receiver.
/// @param rewardAmount The amount of rewards that were distributed.
/// @param nextRewardTime The timestamp after which the next reward can be distributed.
event Notified(uint256 rewardAmount, uint256 nextRewardTime);
/// @notice Thrown if a caller attempts to notify rewards before the reward interval has elapsed.
error RewardTokenNotifierBase__RewardIntervalNotElapsed();
error RewardTokenNotifierBase__InvalidParameter();
/// @notice The contract that will receive reward notifications. Typically an instance of Staker.
INotifiableRewardReceiver public immutable RECEIVER;
/// @notice The ERC20 token in which rewards are denominated.
IERC20 public immutable TOKEN;
/// @notice The minimum value to which the reward interval can be set.
/// @dev If an inheriting contract wants to allow for a shorter reward interval, this value can be
/// overwritten explicitly by the inheriting contract in its own constructor.
uint256 public immutable MIN_REWARD_INTERVAL = 1 days;
/// @notice The maximum value to which the reward interval can be set.
/// @dev If an inheriting contract wants to allow for a longer reward interval, this value can be
/// overwritten explicitly by the inheriting contract in its own constructor.
uint256 public immutable MAX_REWARD_INTERVAL = 365 days;
/// @notice The amount of reward tokens to be distributed in each notification.
uint256 public rewardAmount;
/// @notice The minimum time that must elapse between reward notifications.
uint256 public rewardInterval;
/// @notice The timestamp after which the next reward notification can be sent.
uint256 public nextRewardTime = 0;
/// @param _receiver The contract that will receive reward notifications. Typically an instance
/// of Staker.
/// @param _initialRewardAmount The initial amount of reward tokens to be distributed per
/// notification.
/// @param _initialRewardInterval The initial minimum time that must elapse between
/// notifications.
/// @dev Care must be taken when initializing a reward interval, because the interval until the
/// next notification is saved at the time a `notify` is called. This means, if an unacceptably
/// long reward time is set, the tokens must be revoked and a new notifier must be deployed to
/// resolve the problem.
constructor(
INotifiableRewardReceiver _receiver,
uint256 _initialRewardAmount,
uint256 _initialRewardInterval
) {
RECEIVER = _receiver;
TOKEN = _receiver.REWARD_TOKEN();
_setRewardAmount(_initialRewardAmount);
_setRewardInterval(_initialRewardInterval);
}
/// @notice Notifies the receiver contract of a new reward, sending the reward tokens and
/// triggering the distribution of those tokens to stakers.
/// @dev The reward interval must have elapsed since the last notification.
/// @dev The tokens are "sent" to the receiver contract using whatever mechanism is implemented
/// in the `_sendTokensToReceiver` method.
function notify() external virtual {
if (block.timestamp < nextRewardTime) {
revert RewardTokenNotifierBase__RewardIntervalNotElapsed();
}
nextRewardTime = block.timestamp + rewardInterval;
_sendTokensToReceiver();
RECEIVER.notifyRewardAmount(rewardAmount);
emit Notified(rewardAmount, nextRewardTime);
}
/// @notice Sets a new reward amount to be used in future notifications.
/// @param _newRewardAmount The new amount of reward tokens to distribute per notification.
/// @dev Caller must be the contract owner.
function setRewardAmount(uint256 _newRewardAmount) external virtual {
_checkOwner();
_setRewardAmount(_newRewardAmount);
}
/// @notice Sets a new reward interval to be used between future notifications.
/// @param _newRewardInterval The new minimum time that must elapse between notifications.
/// @dev Caller must be the contract owner.
/// @dev Care must be taken when setting a reward interval, because the interval until the next
/// notification is saved at the time a `notify` is called. This means, if an unacceptably long
/// reward time is set, the tokens must be revoked and a new notifier must be deployed to resolve
/// the problem.
function setRewardInterval(uint256 _newRewardInterval) external virtual {
_checkOwner();
_setRewardInterval(_newRewardInterval);
}
/// @notice Internal helper method which sets a new reward amount.
/// @param _newRewardAmount The new amount of reward tokens to distribute per notification.
function _setRewardAmount(uint256 _newRewardAmount) internal {
if (_newRewardAmount == 0) revert RewardTokenNotifierBase__InvalidParameter();
emit RewardAmountSet(rewardAmount, _newRewardAmount);
rewardAmount = _newRewardAmount;
}
/// @notice Internal helper method which sets a new reward interval.
/// @param _newRewardInterval The new minimum time that must elapse between notifications.
function _setRewardInterval(uint256 _newRewardInterval) internal {
if (_newRewardInterval < MIN_REWARD_INTERVAL || _newRewardInterval > MAX_REWARD_INTERVAL) {
revert RewardTokenNotifierBase__InvalidParameter();
}
emit RewardIntervalSet(rewardInterval, _newRewardInterval);
rewardInterval = _newRewardInterval;
}
/// @notice Internal abstract method which must be implemented by inheritors to send tokens
/// to the receiver contract.
/// @dev This method will be called before the receiver is notified of new rewards. The
/// implementation must ensure that exactly rewardAmount tokens are moved to the receiver.
function _sendTokensToReceiver() internal virtual;
}// 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) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// 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();
}
}
}{
"remappings": [
"staker-test/=lib/staker/test/",
"@openzeppelin/contracts/=lib/staker/lib/openzeppelin-contracts/contracts/",
"ds-test/=lib/staker/lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/staker/lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/staker/lib/openzeppelin-contracts/",
"stGOV-test/=lib/stGOV/test/",
"stGOV/=lib/stGOV/src/",
"staker/=lib/staker/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract INotifiableRewardReceiver","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_initialRewardAmount","type":"uint256"},{"internalType":"uint256","name":"_initialRewardInterval","type":"uint256"},{"internalType":"address","name":"_initialOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","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":"RewardTokenNotifierBase__InvalidParameter","type":"error"},{"inputs":[],"name":"RewardTokenNotifierBase__RewardIntervalNotElapsed","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nextRewardTime","type":"uint256"}],"name":"Notified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRewardAmount","type":"uint256"}],"name":"RewardAmountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRewardAmount","type":"uint256"}],"name":"RewardIntervalSet","type":"event"},{"inputs":[],"name":"MAX_REWARD_INTERVAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_REWARD_INTERVAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECEIVER","outputs":[{"internalType":"contract INotifiableRewardReceiver","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nextRewardTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"notify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRewardAmount","type":"uint256"}],"name":"setRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRewardInterval","type":"uint256"}],"name":"setRewardInterval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101006040526201518060c0526301e1338060e0525f600355348015610023575f5ffd5b50604051610da8380380610da88339810160408190526100429161024a565b838383836001600160a01b03811661007357604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61007c81610113565b506001600160a01b0383166080819052604080516399248ea760e01b815290516399248ea7916004808201926020929091908290030181865afa1580156100c5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e99190610293565b6001600160a01b031660a0526100fe82610162565b610107816101c3565b505050505050506102b5565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b805f0361018257604051631f9ac7fb60e21b815260040160405180910390fd5b60015460408051918252602082018390527f53ec5ac14ec827c0859f27c3d22f4ea8c29f6d64cbe2f92aeb55210ce6f89b35910160405180910390a1600155565b60c0518110806101d4575060e05181115b156101f257604051631f9ac7fb60e21b815260040160405180910390fd5b60025460408051918252602082018390527fe79d576837a40cc1dc753b1b3e79d5c33582fc2c5d5950e15f26a055534889c9910160405180910390a1600255565b6001600160a01b0381168114610247575f5ffd5b50565b5f5f5f5f6080858703121561025d575f5ffd5b845161026881610233565b602086015160408701516060880151929650909450925061028881610233565b939692955090935050565b5f602082840312156102a3575f5ffd5b81516102ae81610233565b9392505050565b60805160a05160c05160e051610a966103125f395f818161010301526105d801525f81816101df01526105af01525f818161014e0152818161024e015261050401525f81816101b8015281816102e101526105270152610a965ff3fe608060405234801561000f575f5ffd5b50600436106100e5575f3560e01c8063a8a65a7811610088578063bec4de3f11610063578063bec4de3f14610201578063e3e842131461020a578063f2fde38b1461021d578063f7b2a7be14610230575f5ffd5b8063a8a65a78146101a0578063ad7430cc146101b3578063b1ff9ba1146101da575f5ffd5b80637f68e195116100c35780637f68e1951461014057806382bfefc814610149578063899f5898146101885780638da5cb5b14610190575f5ffd5b8063095ea7b3146100e95780633a3eab64146100fe578063715018a614610138575b5f5ffd5b6100fc6100f736600461099d565b610239565b005b6101257f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100fc610279565b61012560035481565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012f565b6100fc61028c565b5f546001600160a01b0316610170565b6100fc6101ae3660046109c5565b610387565b6101707f000000000000000000000000000000000000000000000000000000000000000081565b6101257f000000000000000000000000000000000000000000000000000000000000000081565b61012560025481565b6100fc6102183660046109c5565b61039b565b6100fc61022b3660046109dc565b6103ac565b61012560015481565b6102416103eb565b6102756001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168383610417565b5050565b6102816103eb565b61028a5f6104a4565b565b6003544210156102af576040516302dfb46960e01b815260040160405180910390fd5b6002546102bc90426109f5565b6003556102c76104f3565b600154604051633c6b16ab60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633c6b16ab906024015f604051808303815f87803b15801561032a575f5ffd5b505af115801561033c573d5f5f3e3d5ffd5b50506001546003546040517f0fd7bb2818b0aaa42a4064edb68964c3e29810804cf8cce3060a3bac23fb9d79945061037d9350918252602082015260400190565b60405180910390a1565b61038f6103eb565b6103988161054c565b50565b6103a36103eb565b610398816105ad565b6103b46103eb565b6001600160a01b0381166103e257604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b610398816104a4565b5f546001600160a01b0316331461028a5760405163118cdaa760e01b81523360048201526024016103d9565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa158015610464573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104889190610a14565b905061049e848461049985856109f5565b610659565b50505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60015461028a906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016907f000000000000000000000000000000000000000000000000000000000000000090610716565b805f0361056c57604051631f9ac7fb60e21b815260040160405180910390fd5b60015460408051918252602082018390527f53ec5ac14ec827c0859f27c3d22f4ea8c29f6d64cbe2f92aeb55210ce6f89b35910160405180910390a1600155565b7f00000000000000000000000000000000000000000000000000000000000000008110806105fa57507f000000000000000000000000000000000000000000000000000000000000000081115b1561061857604051631f9ac7fb60e21b815260040160405180910390fd5b60025460408051918252602082018390527fe79d576837a40cc1dc753b1b3e79d5c33582fc2c5d5950e15f26a055534889c9910160405180910390a1600255565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526106aa848261074c565b61049e576040516001600160a01b0384811660248301525f604483015261070c91869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506107ef565b61049e84826107ef565b6040516001600160a01b0383811660248301526044820183905261074791859182169063a9059cbb906064016106da565b505050565b5f5f5f846001600160a01b0316846040516107679190610a2b565b5f604051808303815f865af19150503d805f81146107a0576040519150601f19603f3d011682016040523d82523d5f602084013e6107a5565b606091505b50915091508180156107cf5750805115806107cf5750808060200190518101906107cf9190610a41565b80156107e457505f856001600160a01b03163b115b925050505b92915050565b5f6108036001600160a01b03841683610850565b905080515f141580156108275750808060200190518101906108259190610a41565b155b1561074757604051635274afe760e01b81526001600160a01b03841660048201526024016103d9565b606061085d83835f610864565b9392505050565b6060814710156108895760405163cd78605960e01b81523060048201526024016103d9565b5f5f856001600160a01b031684866040516108a49190610a2b565b5f6040518083038185875af1925050503d805f81146108de576040519150601f19603f3d011682016040523d82523d5f602084013e6108e3565b606091505b50915091506108f38683836108fd565b9695505050505050565b6060826109125761090d82610959565b61085d565b815115801561092957506001600160a01b0384163b155b1561095257604051639996b31560e01b81526001600160a01b03851660048201526024016103d9565b508061085d565b8051156109695780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b0381168114610998575f5ffd5b919050565b5f5f604083850312156109ae575f5ffd5b6109b783610982565b946020939093013593505050565b5f602082840312156109d5575f5ffd5b5035919050565b5f602082840312156109ec575f5ffd5b61085d82610982565b808201808211156107e957634e487b7160e01b5f52601160045260245ffd5b5f60208284031215610a24575f5ffd5b5051919050565b5f82518060208501845e5f920191825250919050565b5f60208284031215610a51575f5ffd5b8151801515811461085d575f5ffdfea2646970667358221220ca6e98802504f42dfb93d69136a5ed994f0eef343f7a4e981e78db0b37e8762264736f6c634300081c00330000000000000000000000001f43de0113f059c200172e4274090c54c76cbd280000000000000000000000000000000000000000000005d2c72a2ac16a3000000000000000000000000000000000000000000000000000000000000000278d0000000000000000000000000042d201cc4d9c1e31c032397f54cace2f48c1fa72
Deployed Bytecode
0x608060405234801561000f575f5ffd5b50600436106100e5575f3560e01c8063a8a65a7811610088578063bec4de3f11610063578063bec4de3f14610201578063e3e842131461020a578063f2fde38b1461021d578063f7b2a7be14610230575f5ffd5b8063a8a65a78146101a0578063ad7430cc146101b3578063b1ff9ba1146101da575f5ffd5b80637f68e195116100c35780637f68e1951461014057806382bfefc814610149578063899f5898146101885780638da5cb5b14610190575f5ffd5b8063095ea7b3146100e95780633a3eab64146100fe578063715018a614610138575b5f5ffd5b6100fc6100f736600461099d565b610239565b005b6101257f0000000000000000000000000000000000000000000000000000000001e1338081565b6040519081526020015b60405180910390f35b6100fc610279565b61012560035481565b6101707f0000000000000000000000000b010000b7624eb9b3dfbc279673c76e9d29d5f781565b6040516001600160a01b03909116815260200161012f565b6100fc61028c565b5f546001600160a01b0316610170565b6100fc6101ae3660046109c5565b610387565b6101707f0000000000000000000000001f43de0113f059c200172e4274090c54c76cbd2881565b6101257f000000000000000000000000000000000000000000000000000000000001518081565b61012560025481565b6100fc6102183660046109c5565b61039b565b6100fc61022b3660046109dc565b6103ac565b61012560015481565b6102416103eb565b6102756001600160a01b037f0000000000000000000000000b010000b7624eb9b3dfbc279673c76e9d29d5f7168383610417565b5050565b6102816103eb565b61028a5f6104a4565b565b6003544210156102af576040516302dfb46960e01b815260040160405180910390fd5b6002546102bc90426109f5565b6003556102c76104f3565b600154604051633c6b16ab60e01b815260048101919091527f0000000000000000000000001f43de0113f059c200172e4274090c54c76cbd286001600160a01b031690633c6b16ab906024015f604051808303815f87803b15801561032a575f5ffd5b505af115801561033c573d5f5f3e3d5ffd5b50506001546003546040517f0fd7bb2818b0aaa42a4064edb68964c3e29810804cf8cce3060a3bac23fb9d79945061037d9350918252602082015260400190565b60405180910390a1565b61038f6103eb565b6103988161054c565b50565b6103a36103eb565b610398816105ad565b6103b46103eb565b6001600160a01b0381166103e257604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b610398816104a4565b5f546001600160a01b0316331461028a5760405163118cdaa760e01b81523360048201526024016103d9565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa158015610464573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104889190610a14565b905061049e848461049985856109f5565b610659565b50505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60015461028a906001600160a01b037f0000000000000000000000000b010000b7624eb9b3dfbc279673c76e9d29d5f716907f0000000000000000000000001f43de0113f059c200172e4274090c54c76cbd2890610716565b805f0361056c57604051631f9ac7fb60e21b815260040160405180910390fd5b60015460408051918252602082018390527f53ec5ac14ec827c0859f27c3d22f4ea8c29f6d64cbe2f92aeb55210ce6f89b35910160405180910390a1600155565b7f00000000000000000000000000000000000000000000000000000000000151808110806105fa57507f0000000000000000000000000000000000000000000000000000000001e1338081115b1561061857604051631f9ac7fb60e21b815260040160405180910390fd5b60025460408051918252602082018390527fe79d576837a40cc1dc753b1b3e79d5c33582fc2c5d5950e15f26a055534889c9910160405180910390a1600255565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526106aa848261074c565b61049e576040516001600160a01b0384811660248301525f604483015261070c91869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506107ef565b61049e84826107ef565b6040516001600160a01b0383811660248301526044820183905261074791859182169063a9059cbb906064016106da565b505050565b5f5f5f846001600160a01b0316846040516107679190610a2b565b5f604051808303815f865af19150503d805f81146107a0576040519150601f19603f3d011682016040523d82523d5f602084013e6107a5565b606091505b50915091508180156107cf5750805115806107cf5750808060200190518101906107cf9190610a41565b80156107e457505f856001600160a01b03163b115b925050505b92915050565b5f6108036001600160a01b03841683610850565b905080515f141580156108275750808060200190518101906108259190610a41565b155b1561074757604051635274afe760e01b81526001600160a01b03841660048201526024016103d9565b606061085d83835f610864565b9392505050565b6060814710156108895760405163cd78605960e01b81523060048201526024016103d9565b5f5f856001600160a01b031684866040516108a49190610a2b565b5f6040518083038185875af1925050503d805f81146108de576040519150601f19603f3d011682016040523d82523d5f602084013e6108e3565b606091505b50915091506108f38683836108fd565b9695505050505050565b6060826109125761090d82610959565b61085d565b815115801561092957506001600160a01b0384163b155b1561095257604051639996b31560e01b81526001600160a01b03851660048201526024016103d9565b508061085d565b8051156109695780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b0381168114610998575f5ffd5b919050565b5f5f604083850312156109ae575f5ffd5b6109b783610982565b946020939093013593505050565b5f602082840312156109d5575f5ffd5b5035919050565b5f602082840312156109ec575f5ffd5b61085d82610982565b808201808211156107e957634e487b7160e01b5f52601160045260245ffd5b5f60208284031215610a24575f5ffd5b5051919050565b5f82518060208501845e5f920191825250919050565b5f60208284031215610a51575f5ffd5b8151801515811461085d575f5ffdfea2646970667358221220ca6e98802504f42dfb93d69136a5ed994f0eef343f7a4e981e78db0b37e8762264736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001f43de0113f059c200172e4274090c54c76cbd280000000000000000000000000000000000000000000005d2c72a2ac16a3000000000000000000000000000000000000000000000000000000000000000278d0000000000000000000000000042d201cc4d9c1e31c032397f54cace2f48c1fa72
-----Decoded View---------------
Arg [0] : _receiver (address): 0x1f43De0113f059C200172e4274090c54C76Cbd28
Arg [1] : _initialRewardAmount (uint256): 27500000000000000000000
Arg [2] : _initialRewardInterval (uint256): 2592000
Arg [3] : _initialOwner (address): 0x42D201CC4d9C1e31c032397F54caCE2f48C1FA72
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000001f43de0113f059c200172e4274090c54c76cbd28
Arg [1] : 0000000000000000000000000000000000000000000005d2c72a2ac16a300000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000278d00
Arg [3] : 00000000000000000000000042d201cc4d9c1e31c032397f54cace2f48c1fa72
Deployed Bytecode Sourcemap
966:1633:8:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2080:137;;;;;;:::i;:::-;;:::i;:::-;;3263:55:7;;;;;;;;643:25:9;;;631:2;616:18;3263:55:7;;;;;;;;2293:101:0;;;:::i;3631:33:7:-;;;;;;2664:29;;;;;;;;-1:-1:-1;;;;;857:32:9;;;839:51;;827:2;812:18;2664:29:7;679:217:9;4990:337:7;;;:::i;1638:85:0:-;1684:7;1710:6;-1:-1:-1;;;;;1710:6:0;1638:85;;5546:132:7;;;;;;:::i;:::-;;:::i;2544:51::-;;;;;2952:53;;;;;3515:29;;;;;;6218:140;;;;;;:::i;:::-;;:::i;2543:215:0:-;;;;;;:::i;:::-;;:::i;3405:27:7:-;;;;;;2080:137:8;2147:13;:11;:13::i;:::-;2166:46;-1:-1:-1;;;;;2166:5:8;:27;2194:8;2204:7;2166:27;:46::i;:::-;2080:137;;:::o;2293:101:0:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;4990:337:7:-;5053:14;;5035:15;:32;5031:111;;;5084:51;;-1:-1:-1;;;5084:51:7;;;;;;;;;;;5031:111;5183:14;;5165:32;;:15;:32;:::i;:::-;5148:14;:49;5203:23;:21;:23::i;:::-;5260:12;;5232:41;;-1:-1:-1;;;5232:41:7;;;;;643:25:9;;;;5232:8:7;-1:-1:-1;;;;;5232:27:7;;;;616:18:9;;5232:41:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;5293:12:7;;5307:14;;5284:38;;;;-1:-1:-1;5284:38:7;;-1:-1:-1;2173:25:9;;;2229:2;2214:18;;2207:34;2161:2;2146:18;;1999:248;5284:38:7;;;;;;;;4990:337::o;5546:132::-;5620:13;:11;:13::i;:::-;5639:34;5656:16;5639;:34::i;:::-;5546:132;:::o;6218:140::-;6296:13;:11;:13::i;:::-;6315:38;6334:18;6315;:38::i;2543:215:0:-;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:0;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:0;;2700:1:::1;2672:31;::::0;::::1;839:51:9::0;812:18;;2672:31:0::1;;;;;;;;2623:91;2723:28;2742:8;2723:18;:28::i;1796:162::-:0;1684:7;1710:6;-1:-1:-1;;;;;1710:6:0;735:10:5;1855:23:0;1851:101;;1901:40;;-1:-1:-1;;;1901:40:0;;735:10:5;1901:40:0;;;839:51:9;812:18;;1901:40:0;679:217:9;2081:225:3;2200:39;;-1:-1:-1;;;2200:39:3;;2224:4;2200:39;;;2426:51:9;-1:-1:-1;;;;;2513:32:9;;;2493:18;;;2486:60;2177:20:3;;2200:15;;;;;;2399:18:9;;2200:39:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2177:62;-1:-1:-1;2249:50:3;2262:5;2269:7;2278:20;2293:5;2177:62;2278:20;:::i;:::-;2249:12;:50::i;:::-;2167:139;2081:225;;;:::o;2912:187:0:-;2985:16;3004:6;;-1:-1:-1;;;;;3020:17:0;;;-1:-1:-1;;;;;;3020:17:0;;;;;;3052:40;;3004:6;;;;;;;3052:40;;2985:16;3052:40;2975:124;2912:187;:::o;2476:121:8:-;2579:12;;2541:51;;-1:-1:-1;;;;;2541:5:8;:18;;2568:8;;2541:18;:51::i;6525:245:7:-;6596:16;6616:1;6596:21;6592:77;;6626:43;;-1:-1:-1;;;6626:43:7;;;;;;;;;;;6592:77;6697:12;;6681:47;;;2173:25:9;;;2229:2;2214:18;;2207:34;;;6681:47:7;;2146:18:9;6681:47:7;;;;;;;6734:12;:31;6525:245::o;6938:336::-;7034:19;7013:18;:40;:84;;;;7078:19;7057:18;:40;7013:84;7009:155;;;7114:43;;-1:-1:-1;;;7114:43:7;;;;;;;;;;;7009:155;7193:14;;7175:53;;;2173:25:9;;;2229:2;2214:18;;2207:34;;;7175:53:7;;2146:18:9;7175:53:7;;;;;;;7234:14;:35;6938:336::o;3296:380:3:-;3411:47;;;-1:-1:-1;;;;;2938:32:9;;3411:47:3;;;2920:51:9;2987:18;;;;2980:34;;;3411:47:3;;;;;;;;;;2893:18:9;;;;3411:47:3;;;;;;;;-1:-1:-1;;;;;3411:47:3;-1:-1:-1;;;3411:47:3;;;3474:44;3426:13;3411:47;3474:23;:44::i;:::-;3469:201;;3561:43;;-1:-1:-1;;;;;2938:32:9;;;3561:43:3;;;2920:51:9;3601:1:3;2987:18:9;;;2980:34;3534:71:3;;3554:5;;3576:13;;;;;2893:18:9;;3561:43:3;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3561:43:3;;;;;;;;;;;3534:19;:71::i;:::-;3619:40;3639:5;3646:12;3619:19;:40::i;1303:160::-;1412:43;;-1:-1:-1;;;;;2938:32:9;;;1412:43:3;;;2920:51:9;2987:18;;;2980:34;;;1385:71:3;;1405:5;;1427:14;;;;;2893:18:9;;1412:43:3;2746:274:9;1385:71:3;1303:160;;;:::o;5189:578::-;5272:4;5574:12;5588:23;5623:5;-1:-1:-1;;;;;5615:19:3;5635:4;5615:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5573:67;;;;5657:7;:69;;;;-1:-1:-1;5669:17:3;;:22;;:56;;;5706:10;5695:30;;;;;;;;;;;;:::i;:::-;5657:103;;;;;5759:1;5738:5;-1:-1:-1;;;;;5730:26:3;;:30;5657:103;5650:110;;;;5189:578;;;;;:::o;4059:629::-;4478:23;4504:33;-1:-1:-1;;;;;4504:27:3;;4532:4;4504:27;:33::i;:::-;4478:59;;4551:10;:17;4572:1;4551:22;;:57;;;;;4589:10;4578:30;;;;;;;;;;;;:::i;:::-;4577:31;4551:57;4547:135;;;4631:40;;-1:-1:-1;;;4631:40:3;;-1:-1:-1;;;;;857:32:9;;4631:40:3;;;839:51:9;812:18;;4631:40:3;679:217:9;2705:151:4;2780:12;2811:38;2833:6;2841:4;2847:1;2811:21;:38::i;:::-;2804:45;2705:151;-1:-1:-1;;;2705:151:4:o;3180:392::-;3279:12;3331:5;3307:21;:29;3303:108;;;3359:41;;-1:-1:-1;;;3359:41:4;;3394:4;3359:41;;;839:51:9;812:18;;3359:41:4;679:217:9;3303:108:4;3421:12;3435:23;3462:6;-1:-1:-1;;;;;3462:11:4;3481:5;3488:4;3462:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3420:73;;;;3510:55;3537:6;3545:7;3554:10;3510:26;:55::i;:::-;3503:62;3180:392;-1:-1:-1;;;;;;3180:392:4:o;4625:582::-;4769:12;4798:7;4793:408;;4821:19;4829:10;4821:7;:19::i;:::-;4793:408;;;5045:17;;:22;:49;;;;-1:-1:-1;;;;;;5071:18:4;;;:23;5045:49;5041:119;;;5121:24;;-1:-1:-1;;;5121:24:4;;-1:-1:-1;;;;;857:32:9;;5121:24:4;;;839:51:9;812:18;;5121:24:4;679:217:9;5041:119:4;-1:-1:-1;5180:10:4;5173:17;;5743:516;5874:17;;:21;5870:383;;6102:10;6096:17;6158:15;6145:10;6141:2;6137:19;6130:44;5870:383;6225:17;;-1:-1:-1;;;6225:17:4;;;;;;;;;;;14:173:9;82:20;;-1:-1:-1;;;;;131:31:9;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:300::-;260:6;268;321:2;309:9;300:7;296:23;292:32;289:52;;;337:1;334;327:12;289:52;360:29;379:9;360:29;:::i;:::-;350:39;458:2;443:18;;;;430:32;;-1:-1:-1;;;192:300:9:o;1109:226::-;1168:6;1221:2;1209:9;1200:7;1196:23;1192:32;1189:52;;;1237:1;1234;1227:12;1189:52;-1:-1:-1;1282:23:9;;1109:226;-1:-1:-1;1109:226:9:o;1581:186::-;1640:6;1693:2;1681:9;1672:7;1668:23;1664:32;1661:52;;;1709:1;1706;1699:12;1661:52;1732:29;1751:9;1732:29;:::i;1772:222::-;1837:9;;;1858:10;;;1855:133;;;1910:10;1905:3;1901:20;1898:1;1891:31;1945:4;1942:1;1935:15;1973:4;1970:1;1963:15;2557:184;2627:6;2680:2;2668:9;2659:7;2655:23;2651:32;2648:52;;;2696:1;2693;2686:12;2648:52;-1:-1:-1;2719:16:9;;2557:184;-1:-1:-1;2557:184:9:o;3312:301::-;3441:3;3479:6;3473:13;3525:6;3518:4;3510:6;3506:17;3501:3;3495:37;3587:1;3551:16;;3576:13;;;-1:-1:-1;3551:16:9;3312:301;-1:-1:-1;3312:301:9:o;3618:277::-;3685:6;3738:2;3726:9;3717:7;3713:23;3709:32;3706:52;;;3754:1;3751;3744:12;3706:52;3786:9;3780:16;3839:5;3832:13;3825:21;3818:5;3815:32;3805:60;;3861:1;3858;3851:12
Swarm Source
ipfs://ca6e98802504f42dfb93d69136a5ed994f0eef343f7a4e981e78db0b37e87622
Loading...
Loading
Loading...
Loading
Net Worth in USD
$994.67
Net Worth in ETH
0.501457
Token Allocations
OBOL
100.00%
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $0.018085 | 55,000 | $994.67 |
Loading...
Loading
Loading...
Loading
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.