S Price: $0.06735 (+2.47%)
Gas: 55 Gwei

Contract

0x7464402B9495b5De7Bd355ED4f9A45E45566Ccc4

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Stake546218252025-11-09 20:50:1077 days ago1762721410IN
0x7464402B...45566Ccc4
0 S0.0052052550
Unstake517249042025-10-24 6:15:0894 days ago1761286508IN
0x7464402B...45566Ccc4
0 S0.0042212550.0001
Claim515341732025-10-22 12:44:3796 days ago1761137077IN
0x7464402B...45566Ccc4
0 S0.0027826550.0001
Unstake508888322025-10-16 19:00:20102 days ago1760641220IN
0x7464402B...45566Ccc4
0 S0.0041273655
Prepare Unstake498478322025-10-09 3:23:14109 days ago1759980194IN
0x7464402B...45566Ccc4
0 S0.0077680955
Unstake498104142025-10-08 18:52:58110 days ago1759949578IN
0x7464402B...45566Ccc4
0 S0.0035982550.34642857
Unstake492526632025-10-03 21:31:55114 days ago1759527115IN
0x7464402B...45566Ccc4
0 S0.0039974555
Unstake492526362025-10-03 21:31:29114 days ago1759527089IN
0x7464402B...45566Ccc4
0 S0.0041273655
Restake485140962025-09-28 0:51:04120 days ago1759020664IN
0x7464402B...45566Ccc4
0 S0.0024755550.0001
Prepare Unstake485139792025-09-28 0:49:53120 days ago1759020593IN
0x7464402B...45566Ccc4
0 S0.0065844650.0001
Stake485139362025-09-28 0:49:24120 days ago1759020564IN
0x7464402B...45566Ccc4
0 S0.0051181650.0001
Stake481824972025-09-25 17:21:19123 days ago1758820879IN
0x7464402B...45566Ccc4
0 S0.0037760855
Claim479652022025-09-24 0:21:13124 days ago1758673273IN
0x7464402B...45566Ccc4
0 S0.00431760
Prepare Unstake473201632025-09-18 21:21:59129 days ago1758230519IN
0x7464402B...45566Ccc4
0 S0.0090776455
Unstake473176172025-09-18 20:48:30130 days ago1758228510IN
0x7464402B...45566Ccc4
0 S0.0049936555.729
Unstake473175982025-09-18 20:48:16130 days ago1758228496IN
0x7464402B...45566Ccc4
0 S0.0053763660
Claim473030842025-09-18 17:48:27130 days ago1758217707IN
0x7464402B...45566Ccc4
0 S0.0039572555
Prepare Unstake473030672025-09-18 17:48:16130 days ago1758217696IN
0x7464402B...45566Ccc4
0 S0.0089166555
Prepare Unstake472934662025-09-18 15:55:46130 days ago1758210946IN
0x7464402B...45566Ccc4
0 S0.0015128355
Claim465313452025-09-11 20:32:53137 days ago1757622773IN
0x7464402B...45566Ccc4
0 S0.0027807451.5
Prepare Unstake465313312025-09-11 20:32:43137 days ago1757622763IN
0x7464402B...45566Ccc4
0 S0.0083492351.5
Prepare Unstake465313062025-09-11 20:32:19137 days ago1757622739IN
0x7464402B...45566Ccc4
0 S0.0071217251.5
Claim465312852025-09-11 20:31:59137 days ago1757622719IN
0x7464402B...45566Ccc4
0 S0.0032832251.5
Prepare Unstake461603642025-09-08 14:31:02140 days ago1757341862IN
0x7464402B...45566Ccc4
0 S0.0082971660
Claim461535662025-09-08 13:18:19140 days ago1757337499IN
0x7464402B...45566Ccc4
0 S0.0035063655
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Staking

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;

import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";

import {ScaledNumber} from "./libraries/ScaledNumber.sol";

import {IStaking} from "./interfaces/IStaking.sol";
import {IDistribution} from "./interfaces/IDistribution.sol";
import {Distribution} from "./Distribution.sol";
import {UnstakeRequests} from "./libraries/UnstakeRequests.sol";

contract Staking is IStaking, Distribution {
    using ScaledNumber for uint256;
    using UnstakeRequests for UnstakeRequests.UserUnstakes;

    mapping(address => UnstakeRequests.UserUnstakes) internal _queuedUnstakes;

    uint256 public immutable override unstakeDelay;

    uint256 public override totalPrepared;

    bool public override claimingActivated;

    IERC20 public immutable boomToken;

    constructor(
        uint256 unstakeDelay_,
        address boomToken_
    ) Distribution(boomToken_) {
        unstakeDelay = unstakeDelay_;
        boomToken = IERC20(boomToken_);
    }

    function donateRewards(uint256 tokenQuantity_) external override {
        if (tokenQuantity_ == 0) revert ZeroAmount();
        uint256 divisor_ = totalStaked - totalPrepared; // total active staked amount
        if (divisor_ == 0) revert ZeroBalance();

        IERC20(rewardToken).transferFrom(
            msg.sender,
            address(this),
            tokenQuantity_
        );

        _rewardIntegral += tokenQuantity_.div(divisor_); // increase total rewards per unit

        emit DonatedRewards(msg.sender, tokenQuantity_);
    }

    function claim() external override {
        if (!claimingActivated) revert ClaimingNotActive();

        _claim();
    }

    function stake(uint256 tokenQuantity_) external override {
        stakeFor(tokenQuantity_, msg.sender);
    }

    function listQueuedUnstakeRequests(
        address stakerAddress
    )
        external
        view
        returns (UnstakeRequests.UserUnstakeData[] memory unstakeRequests)
    {
        return _queuedUnstakes[stakerAddress].list();
    }

    function stakeFor(
        uint256 tokenQuantity_,
        address recipientAddress_
    ) public override {
        if (tokenQuantity_ == 0) revert ZeroAmount();
        if (recipientAddress_ == address(0)) revert ZeroAddress();

        _checkpoint(recipientAddress_);

        boomToken.transferFrom(msg.sender, address(this), tokenQuantity_);
        _balances[recipientAddress_] += tokenQuantity_;
        totalStaked += tokenQuantity_;

        emit Staked(msg.sender, recipientAddress_, tokenQuantity_);
    }

    function prepareUnstake(
        uint256 tokenQuantity_
    ) public override returns (uint256 withdrawalID) {
        if (tokenQuantity_ == 0) revert ZeroAmount();
        if (activeBalanceOf(msg.sender) < tokenQuantity_)
            revert InsufficientBalance();

        _checkpoint(msg.sender);
        withdrawalID = _queuedUnstakes[msg.sender].queue(
            tokenQuantity_,
            block.timestamp + unstakeDelay
        );
        totalPrepared += tokenQuantity_;

        emit PreparedUnstake(msg.sender, tokenQuantity_, withdrawalID);
    }

    function activateClaiming() public override onlyOwner {
        if (claimingActivated) revert ClaimingAlreadyActive();

        claimingActivated = true;
    }

    function unstake(uint256 withdrawalId_) public override {
        unstakeFor(msg.sender, withdrawalId_);
    }

    function restake(uint256 withdrawalId_) public override {
        _checkpoint(msg.sender);

        UnstakeRequests.UserUnstake memory withdrawal_ = _queuedUnstakes[
            msg.sender
        ].remove(withdrawalId_);
        totalPrepared -= withdrawal_.amount;

        emit Restaked(msg.sender, withdrawal_.amount);
    }

    function unstakeFor(
        address recipientAddress_,
        uint256 withdrawalId_
    ) public override {
        _checkpoint(msg.sender);

        UnstakeRequests.UserUnstake memory withdrawal_ = _queuedUnstakes[
            msg.sender
        ].remove(withdrawalId_);
        uint256 unstakeTime_ = withdrawal_.unstakeTime;
        if (unstakeTime_ > block.timestamp) revert NotUnstaked();

        uint256 tokenQuantity_ = withdrawal_.amount;

        _balances[msg.sender] -= tokenQuantity_;
        totalStaked -= tokenQuantity_;
        totalPrepared -= tokenQuantity_;

        boomToken.transfer(recipientAddress_, tokenQuantity_);

        emit Unstaked(msg.sender, recipientAddress_, tokenQuantity_);
    }

    function activeBalanceOf(
        address stakerAddress_
    ) public view override(IDistribution, Distribution) returns (uint256) {
        return
            _balances[stakerAddress_] -
            _queuedUnstakes[stakerAddress_].totalQueued;
    }

    function symbol() public view override returns (string memory) {
        return string.concat("st", IERC20Metadata(rewardToken).symbol());
    }

    function name() public view override returns (string memory) {
        return string.concat("Staked ", IERC20Metadata(rewardToken).name());
    }

    function _latestIntegral()
        internal
        view
        virtual
        override
        returns (uint256)
    {
        return _rewardIntegral;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.13;

library ScaledNumber {
    uint8 internal constant _DEFAULT_DECIMALS = 18;

    function div(
        uint256 value,
        uint256 divisor
    ) internal pure returns (uint256) {
        return (value * 10 ** _DEFAULT_DECIMALS) / divisor;
    }

    function mul(
        uint256 value,
        uint256 multiplier
    ) internal pure returns (uint256) {
        return (value * multiplier) / 10 ** _DEFAULT_DECIMALS;
    }

    function absSub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a - b : b - a;
    }
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;

import {IDistribution} from "./IDistribution.sol";
import {UnstakeRequests} from "../libraries/UnstakeRequests.sol";

interface IStaking is IDistribution {
    event Staked(
        address indexed stakerAddress,
        address indexed recipientAddress,
        uint256 tokenQuantity
    );
    event PreparedUnstake(
        address indexed account,
        uint256 tokenQuantity,
        uint256 withdrawalID
    );
    event Unstaked(
        address indexed stakerAddress,
        address indexed recipientAddress,
        uint256 tokenQuantity
    );
    event Restaked(address indexed stakerAddress, uint256 tokenQuantity);

    error NotUnstaked();
    error ClaimingNotActive();
    error ClaimingAlreadyActive();
    error ZeroBalance();
    error ZeroAddress();

    function stake(uint256 tokenQuantity) external;

    function stakeFor(uint256 tokenQuantity, address recipientAddress) external;

    function prepareUnstake(
        uint256 tokenQuantity
    ) external returns (uint256 withdrawalID);

    function unstake(uint256 withdrawalId) external;

    function restake(uint256 withdrawalId) external;

    function unstakeFor(
        address recipientAddress,
        uint256 withdrawalId
    ) external;

    function activateClaiming() external;

    function claimingActivated() external view returns (bool claimingActivated);

    function symbol() external view returns (string memory symbol);

    function name() external view returns (string memory name);

    function totalPrepared() external view returns (uint256 tokenQuantity);

    function listQueuedUnstakeRequests(
        address stakerAddress
    )
        external
        view
        returns (UnstakeRequests.UserUnstakeData[] memory unstakeRequests);

    function unstakeDelay() external view returns (uint256 cooldownPeriod);
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.13;

interface IDistribution {
    event Claimed(address indexed account, uint256 amount);
    event DonatedRewards(address indexed account, uint256 amount);

    error ZeroAmount();
    error InsufficientBalance();

    function claim() external;

    function donateRewards(uint256 amount) external;

    function balanceOf(address account) external view returns (uint256 amount);

    function activeBalanceOf(
        address account
    ) external view returns (uint256 amount);

    function totalStaked() external view returns (uint256 amount);

    function claimable(address account) external view returns (uint256 amount);

    function decimals() external view returns (uint8 decimals);

    function rewardToken() external view returns (address rewardToken);
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.13;

import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";

import {Ownable} from "openzeppelin-contracts/contracts/access/Ownable.sol";

import {ScaledNumber} from "./libraries/ScaledNumber.sol";

import {IDistribution} from "./interfaces/IDistribution.sol";

abstract contract Distribution is IDistribution, Ownable {
    using ScaledNumber for uint256;

    uint256 internal _rewardIntegral;
    mapping(address => uint256) internal _balances;
    mapping(address => uint256) internal _usersRewardIntegral;
    mapping(address => uint256) internal _usersRewards;

    address public immutable override rewardToken;

    uint256 public override totalStaked;

    constructor(address rewardToken_) Ownable(msg.sender) {
        rewardToken = rewardToken_;
    }

    function claimable(
        address account_
    ) public view override returns (uint256) {
        return
            _usersRewards[account_] + _newRewards(account_, _latestIntegral());
    }

    function balanceOf(
        address account_
    ) public view override returns (uint256) {
        return _balances[account_];
    }

    function activeBalanceOf(
        address account
    ) public view virtual override returns (uint256);

    function decimals() public view override returns (uint8) {
        return IERC20Metadata(rewardToken).decimals();
    }

    function _checkpoint(address account_) internal {
        uint256 rewardIntegral_ = _rewardIntegral;
        _usersRewards[account_] += _newRewards(account_, rewardIntegral_);
        _usersRewardIntegral[account_] = rewardIntegral_;
    }

    function _claim() internal {
        _checkpoint(msg.sender);

        uint256 amount_ = _usersRewards[msg.sender];
        if (amount_ == 0) return;

        delete _usersRewards[msg.sender];
        IERC20(rewardToken).transfer(msg.sender, amount_);

        emit Claimed(msg.sender, amount_);
    }

    function _newRewards(
        address account_,
        uint256 rewardIntegral_
    ) internal view returns (uint256) {
        uint256 integral_ = rewardIntegral_ - _usersRewardIntegral[account_];
        return integral_.mul(activeBalanceOf(account_));
    }

    function _latestIntegral() internal view virtual returns (uint256);
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.13;

import {EnumerableSet} from "openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol";

library UnstakeRequests {
    using EnumerableSet for EnumerableSet.UintSet;

    error DoesNotExist();

    struct UserUnstakeData {
        uint256 id;
        uint256 amount;
        uint256 unstakeTime;
    }

    struct UserUnstake {
        uint192 amount;
        uint64 unstakeTime;
    }

    struct UserUnstakes {
        mapping(uint256 => UserUnstake) withdrawals;
        EnumerableSet.UintSet ids;
        uint64 nextId;
        uint192 totalQueued;
    }

    function queue(
        UserUnstakes storage self_,
        uint256 amount_,
        uint256 unstakeTime_
    ) internal returns (uint256) {
        uint256 id = self_.nextId;
        self_.withdrawals[id] = UserUnstake({
            amount: uint192(amount_),
            unstakeTime: uint64(unstakeTime_)
        });
        self_.ids.add(id);
        self_.nextId++;
        self_.totalQueued += uint192(amount_);
        return id;
    }

    function remove(
        UserUnstakes storage self_,
        uint256 id_
    ) internal returns (UserUnstake memory withdrawal) {
        if (!self_.ids.remove(id_)) revert DoesNotExist();
        withdrawal = self_.withdrawals[id_];
        self_.totalQueued -= withdrawal.amount;
        delete self_.withdrawals[id_];
    }

    function list(
        UserUnstakes storage self_
    ) internal view returns (UserUnstakeData[] memory withdrawals) {
        uint256 length_ = self_.ids.length();
        withdrawals = new UserUnstakeData[](length_);
        for (uint256 i_; i_ < length_; i_++) {
            uint256 id_ = self_.ids.at(i_);
            UserUnstake memory withdrawal = self_.withdrawals[id_];
            withdrawals[i_] = UserUnstakeData({
                id: id_,
                amount: withdrawal.amount,
                unstakeTime: withdrawal.unstakeTime
            });
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(bytes32 value => uint256) _positions;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._positions[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We cache the value's position to prevent multiple reads from the same storage slot
        uint256 position = set._positions[value];

        if (position != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 valueIndex = position - 1;
            uint256 lastIndex = set._values.length - 1;

            if (valueIndex != lastIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._positions[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }
}

// 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;
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"uint256","name":"unstakeDelay_","type":"uint256"},{"internalType":"address","name":"boomToken_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ClaimingAlreadyActive","type":"error"},{"inputs":[],"name":"ClaimingNotActive","type":"error"},{"inputs":[],"name":"DoesNotExist","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"NotUnstaked","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":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"inputs":[],"name":"ZeroBalance","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DonatedRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenQuantity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawalID","type":"uint256"}],"name":"PreparedUnstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenQuantity","type":"uint256"}],"name":"Restaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipientAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenQuantity","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakerAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipientAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenQuantity","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"activateClaiming","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"stakerAddress_","type":"address"}],"name":"activeBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boomToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimingActivated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenQuantity_","type":"uint256"}],"name":"donateRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"stakerAddress","type":"address"}],"name":"listQueuedUnstakeRequests","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unstakeTime","type":"uint256"}],"internalType":"struct UnstakeRequests.UserUnstakeData[]","name":"unstakeRequests","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenQuantity_","type":"uint256"}],"name":"prepareUnstake","outputs":[{"internalType":"uint256","name":"withdrawalID","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"withdrawalId_","type":"uint256"}],"name":"restake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenQuantity_","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenQuantity_","type":"uint256"},{"internalType":"address","name":"recipientAddress_","type":"address"}],"name":"stakeFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPrepared","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"withdrawalId_","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstakeDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipientAddress_","type":"address"},{"internalType":"uint256","name":"withdrawalId_","type":"uint256"}],"name":"unstakeFor","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60e060405234801561001057600080fd5b50604051611a0f380380611a0f83398101604081905261002f916100cd565b80338061005657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61005f8161007d565b506001600160a01b0390811660805260a0929092521660c05261010a565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080604083850312156100e057600080fd5b825160208401519092506001600160a01b03811681146100ff57600080fd5b809150509250929050565b60805160a05160c05161189e610171600039600081816101b201528181610701015261089301526000818161023b01526104be015260008181610392015281816103b80152818161059e015281816109ea01528181610bb20152610fa4015261189e6000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c806351746bb2116100de57806395d89b4111610097578063bce1b52011610071578063bce1b52014610354578063decb7bcb14610367578063f2fde38b1461037a578063f7c618c11461038d57600080fd5b806395d89b4114610319578063a694fc3a14610321578063b46befd61461033457600080fd5b806351746bb2146102a857806359f769a9146102bb57806370a08231146102ce578063715018a6146102f7578063817b1cd2146102ff5780638da5cb5b1461030857600080fd5b8063313ce56711610130578063313ce5671461021c5780633222012f1461023657806336ef088c1461025d5780633dd669a014610270578063402914f51461028d5780634e71d92d146102a057600080fd5b806306fdde0314610178578063149ee6a51461019657806324b951f9146101ad578063265c7760146101ec5780632e17de78146101ff5780632e7e876814610214575b600080fd5b6101806103b4565b60405161018d91906113ca565b60405180910390f35b61019f60075481565b60405190815260200161018d565b6101d47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161018d565b61019f6101fa3660046113fd565b610460565b61021261020d3660046113fd565b610552565b005b61021261055f565b61022461059a565b60405160ff909116815260200161018d565b61019f7f000000000000000000000000000000000000000000000000000000000000000081565b61021261026b366004611432565b610623565b60085461027d9060ff1681565b604051901515815260200161018d565b61019f61029b36600461145c565b6107b6565b6102126107f3565b6102126102b6366004611477565b610820565b61019f6102c936600461145c565b610993565b61019f6102dc36600461145c565b6001600160a01b031660009081526002602052604090205490565b6102126109d4565b61019f60055481565b6000546001600160a01b03166101d4565b6101806109e6565b61021261032f3660046113fd565b610a7e565b61034761034236600461145c565b610a88565b60405161018d91906114a3565b6102126103623660046113fd565b610aac565b6102126103753660046113fd565b610b3a565b61021261038836600461145c565b610c7a565b6101d47f000000000000000000000000000000000000000000000000000000000000000081565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610414573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261043c9190810190611518565b60405160200161044c91906115ca565b604051602081830303815290604052905090565b60008160000361048357604051631f2a200560e01b815260040160405180910390fd5b8161048d33610993565b10156104ac57604051631e9acf1760e31b815260040160405180910390fd5b6104b533610cba565b6104f9826104e37f00000000000000000000000000000000000000000000000000000000000000004261160f565b3360009081526006602052604090209190610d10565b9050816007600082825461050d919061160f565b9091555050604080518381526020810183905233917ff6fd3987ffa89628a233283807e8912d77e55fe1289879e7067c23279c0ae22e910160405180910390a2919050565b61055c3382610623565b50565b610567610e02565b60085460ff161561058b576040516351c7305760e11b815260040160405180910390fd5b6008805460ff19166001179055565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061e9190611622565b905090565b61062c33610cba565b3360009081526006602052604081206106459083610e2f565b60208101519091506001600160401b03164281111561067757604051630b2aa99d60e01b815260040160405180910390fd5b815133600090815260026020526040812080546001600160c01b03909316928392906106a4908490611645565b9250508190555080600560008282546106bd9190611645565b9250508190555080600760008282546106d69190611645565b909155505060405163a9059cbb60e01b81526001600160a01b038681166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af115801561074a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076e9190611658565b506040518181526001600160a01b0386169033907fd8654fcc8cf5b36d30b3f5e4688fc78118e6d68de60b9994e09902268b57c3e39060200160405180910390a35050505050565b60006107ca826107c560015490565b610f04565b6001600160a01b0383166000908152600460205260409020546107ed919061160f565b92915050565b60085460ff16610816576040516321f143f360e11b815260040160405180910390fd5b61081e610f46565b565b8160000361084157604051631f2a200560e01b815260040160405180910390fd5b6001600160a01b0381166108685760405163d92e233d60e01b815260040160405180910390fd5b61087181610cba565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156108e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109089190611658565b506001600160a01b0381166000908152600260205260408120805484929061093190849061160f565b92505081905550816005600082825461094a919061160f565b90915550506040518281526001600160a01b0382169033907f5dac0c1b1112564a045ba943c9d50270893e8e826c49be8e7073adc713ab7bd79060200160405180910390a35050565b6001600160a01b03811660009081526006602090815260408083206003015460029092528220546107ed91600160401b90046001600160c01b031690611645565b6109dc610e02565b61081e600061104a565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610a46573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a6e9190810190611518565b60405160200161044c919061167a565b61055c8133610820565b6001600160a01b03811660009081526006602052604090206060906107ed9061109a565b610ab533610cba565b336000908152600660205260408120610ace9083610e2f565b905080600001516001600160c01b031660076000828254610aef9190611645565b909155505080516040516001600160c01b03909116815233907ffc11547e675aec955dee8afa8fab2509420a3a91ca90e88b9b95db75bdf4c00b906020015b60405180910390a25050565b80600003610b5b57604051631f2a200560e01b815260040160405180910390fd5b6000600754600554610b6d9190611645565b905080600003610b905760405163334ab3f560e11b815260040160405180910390fd5b6040516323b872dd60e01b8152336004820152306024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af1158015610c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c279190611658565b50610c3282826111ca565b60016000828254610c43919061160f565b909155505060405182815233907f7e5b4f1ecd550783305a91024850d04a590ca64a1977e3352c961fef3f9b770b90602001610b2e565b610c82610e02565b6001600160a01b038116610cb157604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61055c8161104a565b600154610cc78282610f04565b6001600160a01b03831660009081526004602052604081208054909190610cef90849061160f565b90915550506001600160a01b03909116600090815260036020526040902055565b60038301546040805180820182526001600160c01b0380861682526001600160401b0385811660208085019182529582166000818152968a905294862093519051909116600160c01b029116179055610d6c60018601826111f4565b506003850180546001600160401b0316906000610d88836116a4565b91906101000a8154816001600160401b0302191690836001600160401b0316021790555050838560030160088282829054906101000a90046001600160c01b0316610dd391906116cf565b92506101000a8154816001600160c01b0302191690836001600160c01b03160217905550809150509392505050565b6000546001600160a01b0316331461081e5760405163118cdaa760e01b8152336004820152602401610ca8565b6040805180820190915260008082526020820152610e506001840183611200565b610e6d5760405163b0ce759160e01b815260040160405180910390fd5b50600081815260208381526040918290208251808401909352546001600160c01b03808216808552600160c01b9092046001600160401b03169284019290925260038501805491929091600891610ece918591600160401b909104166116ee565b82546001600160c01b039182166101009390930a9283029190920219909116179055506000918252602092909252604081205590565b6001600160a01b0382166000908152600360205260408120548190610f299084611645565b9050610f3e610f3785610993565b829061120c565b949350505050565b610f4f33610cba565b3360009081526004602052604081205490819003610f6a5750565b33600081815260046020819052604080832092909255905163a9059cbb60e01b815290810191909152602481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610fed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110119190611658565b5060405181815233907fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a9060200160405180910390a250565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b606060006110aa83600101611224565b9050806001600160401b038111156110c4576110c4611502565b60405190808252806020026020018201604052801561111957816020015b61110660405180606001604052806000815260200160008152602001600081525090565b8152602001906001900390816110e25790505b50915060005b818110156111c3576000611136600186018361122e565b600081815260208781526040918290208251808401845290546001600160c01b0380821683526001600160401b03600160c01b9092048216838501908152855160608101875287815284519092169482019490945292511692820192909252865192935090918690859081106111ae576111ae61170d565b6020908102919091010152505060010161111f565b5050919050565b6000816111d96012600a61180a565b6111e39085611819565b6111ed9190611830565b9392505050565b60006111ed838361123a565b60006111ed8383611289565b600061121a6012600a61180a565b6111e38385611819565b60006107ed825490565b60006111ed838361137c565b6000818152600183016020526040812054611281575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107ed565b5060006107ed565b600081815260018301602052604081205480156113725760006112ad600183611645565b85549091506000906112c190600190611645565b90508082146113265760008660000182815481106112e1576112e161170d565b90600052602060002001549050808760000184815481106113045761130461170d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061133757611337611852565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506107ed565b60009150506107ed565b60008260000182815481106113935761139361170d565b9060005260206000200154905092915050565b60005b838110156113c15781810151838201526020016113a9565b50506000910152565b60208152600082518060208401526113e98160408501602087016113a6565b601f01601f19169190910160400192915050565b60006020828403121561140f57600080fd5b5035919050565b80356001600160a01b038116811461142d57600080fd5b919050565b6000806040838503121561144557600080fd5b61144e83611416565b946020939093013593505050565b60006020828403121561146e57600080fd5b6111ed82611416565b6000806040838503121561148a57600080fd5b8235915061149a60208401611416565b90509250929050565b602080825282518282018190526000918401906040840190835b818110156114f7578351805184526020810151602085015260408101516040850152506060830192506020840193506001810190506114bd565b509095945050505050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561152a57600080fd5b81516001600160401b0381111561154057600080fd5b8201601f8101841361155157600080fd5b80516001600160401b0381111561156a5761156a611502565b604051601f8201601f19908116603f011681016001600160401b038111828210171561159857611598611502565b6040528181528282016020018610156115b057600080fd5b6115c18260208301602086016113a6565b95945050505050565b66029ba30b5b2b2160cd1b8152600082516115ec8160078501602087016113a6565b9190910160070192915050565b634e487b7160e01b600052601160045260246000fd5b808201808211156107ed576107ed6115f9565b60006020828403121561163457600080fd5b815160ff811681146111ed57600080fd5b818103818111156107ed576107ed6115f9565b60006020828403121561166a57600080fd5b815180151581146111ed57600080fd5b611cdd60f21b8152600082516116978160028501602087016113a6565b9190910160020192915050565b60006001600160401b0382166001600160401b0381036116c6576116c66115f9565b60010192915050565b6001600160c01b0381811683821601908111156107ed576107ed6115f9565b6001600160c01b0382811682821603908111156107ed576107ed6115f9565b634e487b7160e01b600052603260045260246000fd5b6001815b600184111561175e57808504811115611742576117426115f9565b600184161561175057908102905b60019390931c928002611727565b935093915050565b600082611775575060016107ed565b81611782575060006107ed565b816001811461179857600281146117a2576117be565b60019150506107ed565b60ff8411156117b3576117b36115f9565b50506001821b6107ed565b5060208310610133831016604e8410600b84101617156117e1575081810a6107ed565b6117ee6000198484611723565b8060001904821115611802576118026115f9565b029392505050565b60006111ed60ff841683611766565b80820281158282048414176107ed576107ed6115f9565b60008261184d57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603160045260246000fdfea26469706673582212206a8d4f18b305a9c4f54ca18cc06d60f4a2c8a2ec1d1188e4faa00622e8fbccf964736f6c634300081c00330000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada46

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101735760003560e01c806351746bb2116100de57806395d89b4111610097578063bce1b52011610071578063bce1b52014610354578063decb7bcb14610367578063f2fde38b1461037a578063f7c618c11461038d57600080fd5b806395d89b4114610319578063a694fc3a14610321578063b46befd61461033457600080fd5b806351746bb2146102a857806359f769a9146102bb57806370a08231146102ce578063715018a6146102f7578063817b1cd2146102ff5780638da5cb5b1461030857600080fd5b8063313ce56711610130578063313ce5671461021c5780633222012f1461023657806336ef088c1461025d5780633dd669a014610270578063402914f51461028d5780634e71d92d146102a057600080fd5b806306fdde0314610178578063149ee6a51461019657806324b951f9146101ad578063265c7760146101ec5780632e17de78146101ff5780632e7e876814610214575b600080fd5b6101806103b4565b60405161018d91906113ca565b60405180910390f35b61019f60075481565b60405190815260200161018d565b6101d47f000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada4681565b6040516001600160a01b03909116815260200161018d565b61019f6101fa3660046113fd565b610460565b61021261020d3660046113fd565b610552565b005b61021261055f565b61022461059a565b60405160ff909116815260200161018d565b61019f7f0000000000000000000000000000000000000000000000000000000000093a8081565b61021261026b366004611432565b610623565b60085461027d9060ff1681565b604051901515815260200161018d565b61019f61029b36600461145c565b6107b6565b6102126107f3565b6102126102b6366004611477565b610820565b61019f6102c936600461145c565b610993565b61019f6102dc36600461145c565b6001600160a01b031660009081526002602052604090205490565b6102126109d4565b61019f60055481565b6000546001600160a01b03166101d4565b6101806109e6565b61021261032f3660046113fd565b610a7e565b61034761034236600461145c565b610a88565b60405161018d91906114a3565b6102126103623660046113fd565b610aac565b6102126103753660046113fd565b610b3a565b61021261038836600461145c565b610c7a565b6101d47f000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada4681565b60607f000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada466001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610414573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261043c9190810190611518565b60405160200161044c91906115ca565b604051602081830303815290604052905090565b60008160000361048357604051631f2a200560e01b815260040160405180910390fd5b8161048d33610993565b10156104ac57604051631e9acf1760e31b815260040160405180910390fd5b6104b533610cba565b6104f9826104e37f0000000000000000000000000000000000000000000000000000000000093a804261160f565b3360009081526006602052604090209190610d10565b9050816007600082825461050d919061160f565b9091555050604080518381526020810183905233917ff6fd3987ffa89628a233283807e8912d77e55fe1289879e7067c23279c0ae22e910160405180910390a2919050565b61055c3382610623565b50565b610567610e02565b60085460ff161561058b576040516351c7305760e11b815260040160405180910390fd5b6008805460ff19166001179055565b60007f000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada466001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061e9190611622565b905090565b61062c33610cba565b3360009081526006602052604081206106459083610e2f565b60208101519091506001600160401b03164281111561067757604051630b2aa99d60e01b815260040160405180910390fd5b815133600090815260026020526040812080546001600160c01b03909316928392906106a4908490611645565b9250508190555080600560008282546106bd9190611645565b9250508190555080600760008282546106d69190611645565b909155505060405163a9059cbb60e01b81526001600160a01b038681166004830152602482018390527f000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada46169063a9059cbb906044016020604051808303816000875af115801561074a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076e9190611658565b506040518181526001600160a01b0386169033907fd8654fcc8cf5b36d30b3f5e4688fc78118e6d68de60b9994e09902268b57c3e39060200160405180910390a35050505050565b60006107ca826107c560015490565b610f04565b6001600160a01b0383166000908152600460205260409020546107ed919061160f565b92915050565b60085460ff16610816576040516321f143f360e11b815260040160405180910390fd5b61081e610f46565b565b8160000361084157604051631f2a200560e01b815260040160405180910390fd5b6001600160a01b0381166108685760405163d92e233d60e01b815260040160405180910390fd5b61087181610cba565b6040516323b872dd60e01b8152336004820152306024820152604481018390527f000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada466001600160a01b0316906323b872dd906064016020604051808303816000875af11580156108e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109089190611658565b506001600160a01b0381166000908152600260205260408120805484929061093190849061160f565b92505081905550816005600082825461094a919061160f565b90915550506040518281526001600160a01b0382169033907f5dac0c1b1112564a045ba943c9d50270893e8e826c49be8e7073adc713ab7bd79060200160405180910390a35050565b6001600160a01b03811660009081526006602090815260408083206003015460029092528220546107ed91600160401b90046001600160c01b031690611645565b6109dc610e02565b61081e600061104a565b60607f000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada466001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610a46573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a6e9190810190611518565b60405160200161044c919061167a565b61055c8133610820565b6001600160a01b03811660009081526006602052604090206060906107ed9061109a565b610ab533610cba565b336000908152600660205260408120610ace9083610e2f565b905080600001516001600160c01b031660076000828254610aef9190611645565b909155505080516040516001600160c01b03909116815233907ffc11547e675aec955dee8afa8fab2509420a3a91ca90e88b9b95db75bdf4c00b906020015b60405180910390a25050565b80600003610b5b57604051631f2a200560e01b815260040160405180910390fd5b6000600754600554610b6d9190611645565b905080600003610b905760405163334ab3f560e11b815260040160405180910390fd5b6040516323b872dd60e01b8152336004820152306024820152604481018390527f000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada466001600160a01b0316906323b872dd906064016020604051808303816000875af1158015610c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c279190611658565b50610c3282826111ca565b60016000828254610c43919061160f565b909155505060405182815233907f7e5b4f1ecd550783305a91024850d04a590ca64a1977e3352c961fef3f9b770b90602001610b2e565b610c82610e02565b6001600160a01b038116610cb157604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61055c8161104a565b600154610cc78282610f04565b6001600160a01b03831660009081526004602052604081208054909190610cef90849061160f565b90915550506001600160a01b03909116600090815260036020526040902055565b60038301546040805180820182526001600160c01b0380861682526001600160401b0385811660208085019182529582166000818152968a905294862093519051909116600160c01b029116179055610d6c60018601826111f4565b506003850180546001600160401b0316906000610d88836116a4565b91906101000a8154816001600160401b0302191690836001600160401b0316021790555050838560030160088282829054906101000a90046001600160c01b0316610dd391906116cf565b92506101000a8154816001600160c01b0302191690836001600160c01b03160217905550809150509392505050565b6000546001600160a01b0316331461081e5760405163118cdaa760e01b8152336004820152602401610ca8565b6040805180820190915260008082526020820152610e506001840183611200565b610e6d5760405163b0ce759160e01b815260040160405180910390fd5b50600081815260208381526040918290208251808401909352546001600160c01b03808216808552600160c01b9092046001600160401b03169284019290925260038501805491929091600891610ece918591600160401b909104166116ee565b82546001600160c01b039182166101009390930a9283029190920219909116179055506000918252602092909252604081205590565b6001600160a01b0382166000908152600360205260408120548190610f299084611645565b9050610f3e610f3785610993565b829061120c565b949350505050565b610f4f33610cba565b3360009081526004602052604081205490819003610f6a5750565b33600081815260046020819052604080832092909255905163a9059cbb60e01b815290810191909152602481018290526001600160a01b037f000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada46169063a9059cbb906044016020604051808303816000875af1158015610fed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110119190611658565b5060405181815233907fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a9060200160405180910390a250565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b606060006110aa83600101611224565b9050806001600160401b038111156110c4576110c4611502565b60405190808252806020026020018201604052801561111957816020015b61110660405180606001604052806000815260200160008152602001600081525090565b8152602001906001900390816110e25790505b50915060005b818110156111c3576000611136600186018361122e565b600081815260208781526040918290208251808401845290546001600160c01b0380821683526001600160401b03600160c01b9092048216838501908152855160608101875287815284519092169482019490945292511692820192909252865192935090918690859081106111ae576111ae61170d565b6020908102919091010152505060010161111f565b5050919050565b6000816111d96012600a61180a565b6111e39085611819565b6111ed9190611830565b9392505050565b60006111ed838361123a565b60006111ed8383611289565b600061121a6012600a61180a565b6111e38385611819565b60006107ed825490565b60006111ed838361137c565b6000818152600183016020526040812054611281575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107ed565b5060006107ed565b600081815260018301602052604081205480156113725760006112ad600183611645565b85549091506000906112c190600190611645565b90508082146113265760008660000182815481106112e1576112e161170d565b90600052602060002001549050808760000184815481106113045761130461170d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061133757611337611852565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506107ed565b60009150506107ed565b60008260000182815481106113935761139361170d565b9060005260206000200154905092915050565b60005b838110156113c15781810151838201526020016113a9565b50506000910152565b60208152600082518060208401526113e98160408501602087016113a6565b601f01601f19169190910160400192915050565b60006020828403121561140f57600080fd5b5035919050565b80356001600160a01b038116811461142d57600080fd5b919050565b6000806040838503121561144557600080fd5b61144e83611416565b946020939093013593505050565b60006020828403121561146e57600080fd5b6111ed82611416565b6000806040838503121561148a57600080fd5b8235915061149a60208401611416565b90509250929050565b602080825282518282018190526000918401906040840190835b818110156114f7578351805184526020810151602085015260408101516040850152506060830192506020840193506001810190506114bd565b509095945050505050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561152a57600080fd5b81516001600160401b0381111561154057600080fd5b8201601f8101841361155157600080fd5b80516001600160401b0381111561156a5761156a611502565b604051601f8201601f19908116603f011681016001600160401b038111828210171561159857611598611502565b6040528181528282016020018610156115b057600080fd5b6115c18260208301602086016113a6565b95945050505050565b66029ba30b5b2b2160cd1b8152600082516115ec8160078501602087016113a6565b9190910160070192915050565b634e487b7160e01b600052601160045260246000fd5b808201808211156107ed576107ed6115f9565b60006020828403121561163457600080fd5b815160ff811681146111ed57600080fd5b818103818111156107ed576107ed6115f9565b60006020828403121561166a57600080fd5b815180151581146111ed57600080fd5b611cdd60f21b8152600082516116978160028501602087016113a6565b9190910160020192915050565b60006001600160401b0382166001600160401b0381036116c6576116c66115f9565b60010192915050565b6001600160c01b0381811683821601908111156107ed576107ed6115f9565b6001600160c01b0382811682821603908111156107ed576107ed6115f9565b634e487b7160e01b600052603260045260246000fd5b6001815b600184111561175e57808504811115611742576117426115f9565b600184161561175057908102905b60019390931c928002611727565b935093915050565b600082611775575060016107ed565b81611782575060006107ed565b816001811461179857600281146117a2576117be565b60019150506107ed565b60ff8411156117b3576117b36115f9565b50506001821b6107ed565b5060208310610133831016604e8410600b84101617156117e1575081810a6107ed565b6117ee6000198484611723565b8060001904821115611802576118026115f9565b029392505050565b60006111ed60ff841683611766565b80820281158282048414176107ed576107ed6115f9565b60008261184d57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603160045260246000fdfea26469706673582212206a8d4f18b305a9c4f54ca18cc06d60f4a2c8a2ec1d1188e4faa00622e8fbccf964736f6c634300081c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada46

-----Decoded View---------------
Arg [0] : unstakeDelay_ (uint256): 604800
Arg [1] : boomToken_ (address): 0xcc17DBc9EB1c29f90388Fa197b983714fdAaDa46

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000093a80
Arg [1] : 000000000000000000000000cc17dbc9eb1c29f90388fa197b983714fdaada46


Block Transaction Gas Used Reward
view all blocks ##produced##

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.