ETH Price: $3,348.09 (+0.38%)
Gas: 4.08 Gwei
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Release Lock Tok...205797822024-08-21 21:49:35132 days ago1724276975IN
0xee47A8F3...661468f55
0 ETH0.000257831.61983065

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
188162422023-12-18 23:47:47379 days ago1702943267  Contract Creation0 ETH
Loading...
Loading

Minimal Proxy Contract for 0x4349c26add0552a045a51197d2271be0f25a3463

Contract Name:
VestingWalletGETImplementation

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 20000 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 8 : VestingWalletGETImplementation.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
import "openzeppelin-contracts/utils/Address.sol";
import "openzeppelin-contracts/utils/Context.sol";
import "openzeppelin-contracts/token/ERC20/IERC20.sol";
import "./interfaces/ILockedRevenueDistributionToken.sol";

import "openzeppelin-contracts/proxy/utils/Initializable.sol";

/**
 * @title VestingWalletGETImplementation
 * @dev This contract handles the vesting of ERC20 tokens for a given beneficiary. Custody of multiple tokens
 * can be given to this contract, which will release the token to the beneficiary following a given vesting schedule.
 * The vesting schedule is customizable through the {vestedAmount} function.
 *
 * Any token transferred to this contract will follow the vesting schedule as if they were locked from the beginning.
 * Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly)
 * be immediately releasable.
 */
contract VestingWalletGETImplementation is Context, Initializable {
    // events
    event AdminAccessBurned();
    event EtherSaved(uint256 amount);
    event ERC20Released(address indexed token, uint256 amount);
    event AdminWithdraw(address indexed token, uint256 amount);
    event NothingToClaim();
    event UnlockedTokensStaked(uint256 amountUnlocked, uint256 amountStaked);

    address private beneficiary_;

    uint256 private constant cooldownPeriod_ = 30 days;
    uint256 private lastReleased_;
    mapping(address => uint256) private _erc20Released;
    ILockedRevenueDistributionToken public constant stakingContract_ =
        ILockedRevenueDistributionToken(0x3e49E9C890Cd5B015A18ed76E7A4093f569f1A04);
    IERC20 public constant lockToken_ = IERC20(0x8a854288a5976036A725879164Ca3e91d30c6A1B);
    uint64 private constant duration_ = 365 days;

    address private constant admin_ = address(0xF989c1694A735b10c2Dac36078fA929cd4235AF5);

    address private administeredBy_;

    bool public adminAccessBurned;

    function initializeVesting(address _beneficiary, uint256 _startMoment) external initializer {
        beneficiary_ = _beneficiary;
        administeredBy_ = admin_;
        lastReleased_ = _startMoment;
    }

    /**
     * @dev Set the beneficiary, start timestamp and vesting duration of the vesting wallet.
     */
    constructor() {}

    /**
     * @dev The contract should be able to receive Eth.
     */
    receive() external payable virtual {}

    /**
     * @dev Getter for the beneficiary address.
     */
    function beneficiary() public view virtual returns (address) {
        return beneficiary_;
    }

    /**
     * @dev Getter for the admin address.
     */
    function administeredBy() public view virtual returns (address) {
        return administeredBy_;
    }

    /**
     * @dev Getter for the start timestamp.
     */
    function start() public view virtual returns (uint256) {
        return lastReleased_;
    }

    /**
     * @dev Getter for the vesting duration.
     */
    function duration() public view virtual returns (uint256) {
        return duration_;
    }

    /**
     * @dev Duration of the cooldown period
     */
    function cooldownPeriod() public view virtual returns (uint256) {
        return cooldownPeriod_;
    }

    /**
     * @dev Timestamp of the last token release
     */
    function lastRelease() public view virtual returns (uint256) {
        return lastReleased_;
    }

    /**
     * @dev Amount of token already released
     */
    function released(address token) public view virtual returns (uint256) {
        return _erc20Released[token];
    }

    /**
     * @dev Release the native token (ether) that was sent to this wallt by accident
     */
    function salvageEthereum() public virtual {
        require(msg.sender == beneficiary(), "VestingWallet: not beneficiary");
        emit EtherSaved(address(this).balance);
        Address.sendValue(payable(beneficiary()), address(this).balance);
    }

    function burnAdminAccess() public virtual {
        require(msg.sender == administeredBy_, "VestingWallet: not administered by admin");
        require(!adminAccessBurned, "VestingWallet: admin access already burned");
        administeredBy_ = address(0);
        adminAccessBurned = true;
        emit AdminAccessBurned();
    }

    /**
     * @notice Withdraw vested tokens by admin
     * @param _tokenAddress address of the token to withdraw
     * @param _withdrawAmount amount of token to withdraw
     */
    function withdrawTokensByAdmin(address _tokenAddress, uint256 _withdrawAmount) external {
        require(msg.sender == administeredBy_, "VestingWallet: not administered by admin");
        require(!adminAccessBurned, "VestingWallet: admin access burned");
        SafeERC20.safeTransfer(IERC20(_tokenAddress), administeredBy_, _withdrawAmount);
        emit AdminWithdraw(_tokenAddress, _withdrawAmount);
    }

    /**
     * @dev Getter for the amount of releasable `token` tokens. `token` should be the address of an
     * IERC20 contract.
     */
    function releasable(address token) public view virtual returns (uint256) {
        uint256 vested_ = vestedAmount(token, uint64(block.timestamp));
        if (vested_ != 0) {
            return vested_ - released(token);
        } else {
            return 0;
        }
    }

    function releaseLockToken() public virtual returns (uint256 amountStakedTokensReleased_) {
        return release(address(lockToken_));
    }

    /**
     * @dev Release the tokens that have already vested.
     * Emits a {ERC20Released} event.
     */
    function release(address token) public virtual returns (uint256 amountStakedTokensReleased_) {
        uint256 amount = releasable(token);
        if (amount != 0) {
            lastReleased_ = block.timestamp;
        } else {
            emit NothingToClaim();
            return 0;
        }
        _erc20Released[token] += amount;
        emit ERC20Released(token, amount);
        SafeERC20.safeApprove(IERC20(token), address(stakingContract_), amount);
        uint256 amountStakedTokens_ = stakingContract_.deposit(amount, beneficiary(), 0);
        emit UnlockedTokensStaked(amount, amountStakedTokens_);
        return amountStakedTokens_;
    }

    /**
     * @dev Calculates the amount of tokens that has already vested. Default implementation is a linear vesting curve.
     */
    function vestedAmount(address token, uint64 timestamp) public view virtual returns (uint256) {
        return _vestingSchedule(IERC20(token).balanceOf(address(this)) + released(token), timestamp);
    }

    /**
     * @dev Virtual implementation of the vesting formula. This returns the amount vested, as a function of time, for
     * an asset given its total historical allocation.
     */
    function _vestingSchedule(uint256 totalAllocation, uint64 timestamp) internal view virtual returns (uint256) {
        if (timestamp <= start()) {
            return 0;
        } else if ((lastReleased_ + cooldownPeriod_) > timestamp) {
            return 0;
        } else if (timestamp > start() + duration()) {
            return totalAllocation;
        } else {
            return (totalAllocation * (timestamp - start())) / duration();
        }
    }
}

File 2 of 8 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../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;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @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, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 3 of 8 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 4 of 8 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

File 5 of 8 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @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 amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` 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 amount
    ) external returns (bool);
}

File 6 of 8 : ILockedRevenueDistributionToken.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.7;

interface ILockedRevenueDistributionToken {
    /**
     * @notice        Represents a withdrawal request, packed into a single word.
     * @custom:member unlockedAt Timestamp after which the withdrawal is unlocked.
     * @custom:member shares     Amount of shares to be burned upon withdrawal execution.
     * @custom:member assets     Amount of assets to be returned to user upon withdrawal execution.
     */
    struct WithdrawalRequest {
        uint32 unlockedAt;
        uint32 lockTime;
        uint96 shares;
        uint96 assets;
    }

    /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    ░░░░                              Events                               ░░░░
    ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/

    /**
     * @notice Emitted when burning shares upon withdrawal request cancellation.
     * @param  assets_ Amount of assets returned to contract address.
     * @param  shares_ Share delta between withdrawal request creation and cancellation.
     */
    event CancellationBurn(uint256 assets_, uint256 shares_);

    /**
     * @notice Emitted when the instant withdrawal fee is set.
     * @param  percentage_ A percentage value from 0 to 100.
     */
    event InstantWithdrawalFeeChanged(uint256 percentage_);

    /**
     * @notice Emitted when time-to-unlock for a standard withdrawal set.
     * @param  lockTime_ Integer length of lock time, e.g. `26 weeks`.
     */
    event LockTimeChanged(uint256 lockTime_);

    /**
     * @notice Emitted when redistributing rewards upon early execution or cancellation of a withdrawal request.
     * @param  assets_ Assets redistributed to remaining stakers.
     */
    event Redistribute(uint256 assets_);

    /**
     * @notice Emitted when refunding shares upon withdrawal request cancellation.
     * @param  receiver_   Account to refund shares to at spot rate.
     * @param  assets_     Equivalent asset value for shares returned.
     * @param  shares_     Amount of shares returned to the receiver.
     */
    event Refund(address indexed receiver_, uint256 assets_, uint256 shares_);

    /**
     * @notice Emitted when fee exemption status has been set for an address.
     * @param  account_ Address in which to apply the exemption.
     * @param  status_  True for exempt, false to remove exemption.
     */
    event WithdrawalFeeExemptionStatusChanged(address indexed account_, bool status_);

    /**
     * @notice Emitted when an instant withdrawal fee is paid.
     * @param  caller_   The caller of the `redeem` or `withdraw` function.
     * @param  receiver_ The receiver of the assets.
     * @param  owner_    The owner of the shares or withdrawal request.
     * @param  fee_      The assets paid as fee.
     */
    event WithdrawalFeePaid(address indexed caller_, address indexed receiver_, address indexed owner_, uint256 fee_);

    /**
     * @notice Emitted when a new withdrawal request has been created for an account.
     * @param  request_ Struct containing shares, assets, and maturity date of the created request.
     * @param  pos_   Index/position of the withdrawal request created.
     */
    event WithdrawalRequestCreated(WithdrawalRequest request_, uint256 pos_);

    /**
     * @notice Emitted when an account cancels any existing withdrawal requests.
     * @param  pos_   Index/position of the withdrawal request cancelled.
     */
    event WithdrawalRequestCancelled(uint256 pos_);

    /**
     * @notice Emitted when a withdrawal request has been executed with shares burned and assets withdrawn.
     * @param  pos_ Index/position of the withdrawal request executed.
     */
    event WithdrawalRequestExecuted(uint256 pos_);

    /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    ░░░░                          State Variables                          ░░░░
    ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/

    /**
     * @notice Constant maximum lock time able to be set using `setLockTime` to avoid permanent lockup.
     * @return maximumLockTime_ Maxmimum lock time integer length, e.g. `104 weeks`.
     */
    function MAXIMUM_LOCK_TIME() external view returns (uint256 maximumLockTime_);

    /**
     * @notice Constant vesting period, used in `updateVestingSchedule`.
     * @return vestingPeriod_ Fixed vesting period, e.g. `2 weeks`.
     */
    function VESTING_PERIOD() external view returns (uint256 vestingPeriod_);

    /**
     * @notice Constant time window in which unlocked withdrawal requests can be executed.
     * @return withdrawalWindow_ Fixed withdrawal window, e.g. `4 weeks`.
     */
    function WITHDRAWAL_WINDOW() external view returns (uint256 withdrawalWindow_);

    /**
     * @notice Percentage withdrawal fee to be applied to instant withdrawals.
     * @return instantWithdrawalFee_ A percentage value from 0 to 100.
     */
    function instantWithdrawalFee() external view returns (uint256 instantWithdrawalFee_);

    /**
     * @notice The lock time set for standard withdrawals to become unlocked.
     * @return lockTime_ Length of lock of a standard withdrawal request, e.g. `26 weeks`.
     */
    function lockTime() external view returns (uint256 lockTime_);

    /**
     * @notice Returns exemption status for a given account. When true then instant withdrawal fee will not apply.
     * @param  account_ Account to check for exemption.
     * @return status_  Exemption status.
     */
    function withdrawalFeeExemptions(address account_) external view returns (bool status_);

    /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    ░░░░                     Administrative Functions                      ░░░░
    ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/

    /**
     * @notice Sets the intstant withdrawal fee, applied when making instant withdrawals or redemptions.
     * @notice Can only be set by owner.
     * @param  percentage_ Fee percentage. Must be an integer between 0 and 100 inclusive.
     */
    function setInstantWithdrawalFee(uint256 percentage_) external;

    /**
     * @notice Sets the lock time for standard withdrawals to become unlocked.
     * @notice Can only be set by owner.
     * @notice Must be lower than MAXIMUM_LOCK_TIME to prevent permanent lockup.
     * @param  lockTime_ Length of lock of a standard withdrawal request.
     */
    function setLockTime(uint256 lockTime_) external;

    /**
     * @notice Sets or unsets an owner address to be exempt from the withdrawal fee.
     * @notice Useful in case of future migrations where an approved contract may be given permission to migrate
     * balances to a new token. Can also be used to exempt third-party vaults from facing withdrawal fee when
     * managing balances, such as lending platform liquidations.
     * @notice Can only be set by contract `owner`.
     * @dev    The zero address cannot be set as exmempt as this will always represent an address that pays fees.
     * @param  owner_  Owner address to exempt from instant withdrawal fees.
     * @param  status_ true to add exemption, false to remove exemption.
     */
    function setWithdrawalFeeExemption(address owner_, bool status_) external;

    /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    ░░░░                         Public Functions                          ░░░░
    ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/

    /**
     * @notice Creates a new withdrawal request for future execution using the shares conversion at the point of
     * request. May only be executed after the unlock date.
     * @notice Transfers shares to the vault contract to reserve them, reducing share balance.
     * @param  shares_ Amount of shares to redeem upon unlock.
     */
    function createWithdrawalRequest(uint256 shares_) external;

    /**
     * @notice Removes an open withdrawal request for the sender.
     * @param  pos_ Index/position of the withdrawal request to be cancelled.
     */
    function cancelWithdrawalRequest(uint256 pos_) external;

    /**
     * @notice Executes an existing withdrawal request for msg.sender. Before the request is unlocked, a percentage
     * fee will be paid, equal to a percentage of the instantWithdrawalFee by time elapsed of the request.
     * @param  pos_ Index/position of the withdrawal request to be executed.
     */
    function executeWithdrawalRequest(uint256 pos_) external;

    /**
     * @notice Executes an existing withdrawal request that has passed its unlock date.
     * @dev    Identical to parent implementation but made public by fixed vesting period and removal of owner check.
     * @return issuanceRate_ Slope of release of newly added assets, scaled up by `precision`.
     * @return freeAssets_   Amount of assets currently released to stakers.
     */
    function updateVestingSchedule() external returns (uint256 issuanceRate_, uint256 freeAssets_);

    /**
     * @notice ERC5143 slippage-protected deposit method. The transaction will revert if the shares to be returned is
     * less than minShares_.
     * @param  assets_    Amount of assets to deposit.
     * @param  receiver_  The receiver of the shares.
     * @param  minShares_ Minimum amount of shares to be returned.
     * @return shares_    Amount of shares returned to receiver_.
     */
    function deposit(uint256 assets_, address receiver_, uint256 minShares_) external returns (uint256 shares_);

    /**
     * @notice ERC5143 slippage-protected mint method. The transaction will revert if the assets to be deducted is
     * greater than maxAssets_.
     * @param  shares_    Amount of shares to mint.
     * @param  receiver_  The receiver of the shares.
     * @param  maxAssets_ Maximum amount of assets to be deducted.
     * @return assets_    Amount of deducted when minting shares.
     */
    function mint(uint256 shares_, address receiver_, uint256 maxAssets_) external returns (uint256 assets_);

    /**
     * @notice ERC5143 slippage-protected redeem method. The transaction will revert if the assets to be returned is
     * less than minAssets_.
     * @param  shares_    Amount of shares to redeem.
     * @param  receiver_  The receiver of the assets.
     * @param  owner_     Owner of shares making redemption.
     * @param  minAssets_ Minimum amount of assets to be returned.
     * @return assets_    Amount of assets returned.
     */
    function redeem(uint256 shares_, address receiver_, address owner_, uint256 minAssets_)
        external
        returns (uint256 assets_);

    /**
     * @notice ERC5143 slippage-protected withdraw method. The transaction will revert if the shares to be deducted is
     * greater than maxShares_.
     * @param  assets_    Amount of assets to withdraw.
     * @param  receiver_  The receiver of the assets.
     * @param  owner_     Owner of shares making withdrawal.
     * @param  maxShares_ Minimum amount of shares to be deducted.
     * @return shares_    Amount of shares deducted.
     */
    function withdraw(uint256 assets_, address receiver_, address owner_, uint256 maxShares_)
        external
        returns (uint256 shares_);

    /*░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    ░░░░                          View Functions                           ░░░░
    ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░*/

    /**
     * @notice Previews a redemption of shares for owner. Applies withdrawal fee if owner does not have an exemption.
     * @param  owner_  Owner of shares making redemption.
     * @param  shares_ Amount of shares to redeem.
     * @return assets_ Assets redeemed for shares for owner.
     * @param  fee_    The assets paid as fee.
     */
    function previewRedeem(uint256 shares_, address owner_) external view returns (uint256 assets_, uint256 fee_);

    /**
     * @notice Previews a withdrawal of assets for owner. Applies withdrawal fee if owner does not have an exemption.
     * @param  owner_  Owner of shares makeing withdrawal.
     * @param  assets_ Amount of assets to withdraw.
     * @return shares_ Shares needed to be burned for owner.
     * @param  fee_    The assets paid as fee.
     */
    function previewWithdraw(uint256 assets_, address owner_) external view returns (uint256 shares_, uint256 fee_);

    /**
     * @notice Previews a withdrawal request execution, calculating the assets returned to the receiver and fee paid.
     * @notice Fee percentage reduces linearly from instantWithdrawalFee until 0 at the unlockedAt timestamp.
     * @param  pos_     Index/position of the withdrawal request to be previewed.
     * @param  owner_   Owner of the withdrawal request.
     * @return request_ The WithdrawalRequest struct within storage.
     * @return assets_  Amount of assets returned to owner if withdrawn.
     * @return fee_     The assets paid as fee.
     */
    function previewWithdrawalRequest(uint256 pos_, address owner_)
        external
        view
        returns (WithdrawalRequest memory request_, uint256 assets_, uint256 fee_);

    /**
     * @notice Returns a count of the number of created withdrawal requests for an account, including cancelled.
     * @param  owner_ Account address of owner of withdrawal requests.
     * @return count_ Number of withdrawal request created for owner account.
     */
    function withdrawalRequestCount(address owner_) external view returns (uint256 count_);

    /**
     * @notice Returns an array of created withdrawal requests for an account, including cancelled.
     * @param  owner_    Account address of owner of withdrawal requests.
     * @return requests_ Array of withdrawal request structs for an owner.
     */
    function withdrawalRequests(address owner_) external view returns (WithdrawalRequest[] memory requests_);

    /**
     * @notice Returns existing withdrawal request for a given account.
     * @param  account_ Account address holding withdrawal request.
     * @param  pos_     Index/position of the withdrawal request in the array.
     * @return request_ Withdrawal request struct found at position for owner.
     */
    function withdrawalRequests(address account_, uint256 pos_)
        external
        view
        returns (WithdrawalRequest memory request_);
}

File 7 of 8 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;

import "../../utils/Address.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     * @custom:oz-retyped-from bool
     */
    uint8 private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint8 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
     * constructor.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        bool isTopLevelCall = !_initializing;
        require(
            (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized < type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint8) {
        return _initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _initializing;
    }
}

File 8 of 8 : draft-IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @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.
 */
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].
     */
    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);
}

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

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"AdminAccessBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AdminWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Released","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EtherSaved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[],"name":"NothingToClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amountUnlocked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountStaked","type":"uint256"}],"name":"UnlockedTokensStaked","type":"event"},{"inputs":[],"name":"adminAccessBurned","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"administeredBy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"beneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnAdminAccess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cooldownPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"duration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"uint256","name":"_startMoment","type":"uint256"}],"name":"initializeVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastRelease","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockToken_","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"releasable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"release","outputs":[{"internalType":"uint256","name":"amountStakedTokensReleased_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"releaseLockToken","outputs":[{"internalType":"uint256","name":"amountStakedTokensReleased_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"released","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"salvageEthereum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingContract_","outputs":[{"internalType":"contract ILockedRevenueDistributionToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"start","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint64","name":"timestamp","type":"uint64"}],"name":"vestedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_withdrawAmount","type":"uint256"}],"name":"withdrawTokensByAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
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  ]
[ 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.