Contract 0xE56DC533EC51662DF5F96BD1e0e4dE8d8AC95FFC

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x5398959e1ab2183c3b5292ef9e841c8a8cfe87a2bdd2f89ab992a990f7b378440x60e060401758238532024-01-30 20:00:45118 days 21 hrs ago0x13e6f9f955149f6f4ff3758f4a1755ae52a88d8d IN  Create: FlowsService0 ETH0.00074278 0.1
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FlowsService

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
paris EvmVersion, BSD-3-Clause license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Arbiscan.io on 2024-01-31
*/

// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.20;

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

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

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)

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

// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

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

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

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

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

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

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

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

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

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

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

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

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

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

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

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.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));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    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");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to
     * 0 before setting it to a non-zero value.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    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");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation 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).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}

interface IPowerTokenFlowsService {
    /// @notice Claims rewards for the caller by transferring them from the LiquidityMining contract to the PowerToken contract.
    /// @param lpTokens An array of LP tokens for which the rewards are to be claimed.
    /// @dev This function calls the `claim` function of the `ILiquidityMining` contract to retrieve the rewards amount to transfer.
    /// It then adds the staked tokens to the `powerToken` contract and transfers the rewards from the `liquidityMining` contract to the `powerToken` contract.
    /// @dev Reverts if the `lpTokens` array is empty.
    /// @dev Reverts if there are no rewards to claim.
    function claimRewardsFromLiquidityMining(address[] calldata lpTokens) external;

    /// @notice Updates the indicators for a given account and LP tokens.
    /// @param account The account address for which the indicators are to be updated.
    /// @param lpTokens An array of LP tokens for which the indicators are to be updated.
    /// @dev This function calls the `updateIndicators` function of the `ILiquidityMining` contract to update the indicators.
    /// @dev Reverts if the `lpTokens` array is empty.
    function updateIndicatorsInLiquidityMining(
        address account,
        address[] calldata lpTokens
    ) external;

    /// @notice Delegates staked tokens by providing LP tokens and corresponding amounts.
    /// @param lpTokens An array of LP tokens to delegate.
    /// @param pwTokenAmounts An array of corresponding amounts of LP tokens to delegate.
    /// @dev This function allows the caller to delegate their staked tokens by providing the LP tokens and their corresponding amounts.
    /// @dev It requires that the length of `lpTokens` is equal to the length of `lpTokenAmounts`.
    /// @dev It reverts if either `lpTokens` or `lpTokenAmounts` arrays are empty.
    function delegatePwTokensToLiquidityMining(
        address[] calldata lpTokens,
        uint256[] calldata pwTokenAmounts
    ) external;

    /// @notice Undelegates staked tokens by providing LP tokens and corresponding amounts.
    /// @param lpTokens An array of LP tokens to undelegate.
    /// @param lpTokenAmounts An array of corresponding amounts of LP tokens to undelegate.
    /// @dev This function allows the caller to undelegate their staked tokens by providing the LP tokens and their corresponding amounts.
    /// @dev It requires that the length of `lpTokens` is equal to the length of `lpTokenAmounts`.
    /// @dev It reverts if either `lpTokens` or `lpTokenAmounts` arrays are empty.
    /// @dev It reverts if the total staked token amount to undelegate is not greater than zero.
    function undelegatePwTokensFromLiquidityMining(
        address[] calldata lpTokens,
        uint256[] calldata lpTokenAmounts
    ) external;
}

/// @title Structures used in the LiquidityMining.
library LiquidityMiningTypes {
    /// @title Struct pair representing delegated pwToken balance
    struct DelegatedPwTokenBalance {
        /// @notice lpToken address
        address lpToken;
        /// @notice The amount of Power Token delegated to lpToken staking pool
        /// @dev value represented in 18 decimals
        uint256 pwTokenAmount;
    }

    /// @title Global indicators used in rewards calculation.
    struct GlobalRewardsIndicators {
        /// @notice powerUp indicator aggregated
        /// @dev It can be changed many times during transaction, represented with 18 decimals
        uint256 aggregatedPowerUp;
        /// @notice composite multiplier in a block described in field blockNumber
        /// @dev It can be changed many times during transaction, represented with 27 decimals
        uint128 compositeMultiplierInTheBlock;
        /// @notice Composite multiplier updated in block {blockNumber} but calculated for PREVIOUS (!) block.
        /// @dev It can be changed once per block, represented with 27 decimals
        uint128 compositeMultiplierCumulativePrevBlock;
        /// @dev It can be changed once per block. Block number in which all other params of this structure are updated
        uint32 blockNumber;
        /// @notice value describing amount of rewards issued per block,
        /// @dev It can be changed at most once per block, represented with 8 decimals
        uint32 rewardsPerBlock;
        /// @notice amount of accrued rewards since inception
        /// @dev It can be changed at most once per block, represented with 18 decimals
        uint88 accruedRewards;
    }

    /// @title Params recorded for a given account. These params are used by the algorithm responsible for rewards distribution.
    /// @dev The structure in storage is updated when account interacts with the LiquidityMining smart contract (stake, unstake, delegate, undelegate, claim)
    struct AccountRewardsIndicators {
        /// @notice `composite multiplier cumulative` is calculated for previous block
        /// @dev represented in 27 decimals
        uint128 compositeMultiplierCumulativePrevBlock;
        /// @notice lpToken account's balance
        uint128 lpTokenBalance;
        /// @notive PowerUp is a result of logarithmic equastion,
        /// @dev  powerUp < 100 *10^18
        uint72 powerUp;
        /// @notice balance of Power Tokens delegated to LiquidityMining
        /// @dev delegatedPwTokenBalance < 10^26 < 2^87
        uint96 delegatedPwTokenBalance;
    }

    struct UpdateLpToken {
        address beneficiary;
        address lpToken;
        uint256 lpTokenAmount;
    }

    struct UpdatePwToken {
        address beneficiary;
        address lpToken;
        uint256 pwTokenAmount;
    }

    struct AccruedRewardsResult {
        address lpToken;
        uint256 rewardsAmount;
    }

    struct AccountRewardResult {
        address lpToken;
        uint256 rewardsAmount;
        uint256 allocatedPwTokens;
    }

    struct AccountIndicatorsResult {
        address lpToken;
        LiquidityMiningTypes.AccountRewardsIndicators indicators;
    }

    struct GlobalIndicatorsResult {
        address lpToken;
        LiquidityMiningTypes.GlobalRewardsIndicators indicators;
    }
}

/// @title The interface for interaction with the LiquidityMining.
/// LiquidityMining is responsible for the distribution of the Power Token rewards to accounts
/// staking lpTokens and / or delegating Power Tokens to LiquidityMining. LpTokens can be staked directly to the LiquidityMining,
/// Power Tokens are a staked version of the [Staked] Tokens minted by the PowerToken smart contract.
interface ILiquidityMining {
    /// @notice Returns the balance of staked lpTokens
    /// @param account the account's address
    /// @param lpToken the address of lpToken
    /// @return balance of the lpTokens staked by the sender
    function balanceOf(address account, address lpToken) external view returns (uint256);

    /// @notice It returns the balance of delegated Power Tokens for a given `account` and the list of lpToken addresses.
    /// @param account address for which to fetch the information about balance of delegated Power Tokens
    /// @param lpTokens list of lpTokens addresses(lpTokens)
    /// @return balances list of {LiquidityMiningTypes.DelegatedPwTokenBalance} structure, with information how much Power Token is delegated per lpToken address.
    function balanceOfDelegatedPwToken(
        address account,
        address[] memory lpTokens
    ) external view returns (LiquidityMiningTypes.DelegatedPwTokenBalance[] memory balances);

    /// @notice Calculates the accrued rewards for multiple LP tokens.
    /// @param lpTokens An array of LP token addresses.
    /// @return An array of `AccruedRewardsResult` structures, containing the LP token address and the accrued rewards amount.
    function calculateAccruedRewards(
        address[] calldata lpTokens
    ) external view returns (LiquidityMiningTypes.AccruedRewardsResult[] memory);

    /// @notice Calculates the rewards earned by an account for multiple LP tokens.
    /// @param account The address of the account for which to calculate rewards.
    /// @param lpTokens An array of LP token addresses.
    /// @return An array of `AccountRewardResult` structures, containing the LP token address, rewards amount, and allocated Power Token balance for the account.
    function calculateAccountRewards(
        address account,
        address[] calldata lpTokens
    ) external view returns (LiquidityMiningTypes.AccountRewardResult[] memory);

    /// @notice method allowing to update the indicators per asset (lpToken).
    /// @param account of which we should update the indicators
    /// @param lpTokens of the staking pools to update the indicators
    function updateIndicators(address account, address[] calldata lpTokens) external;

    /// @notice Adds LP tokens to the liquidity mining for multiple accounts.
    /// @param updateLpToken An array of `UpdateLpToken` structures, each containing the account address,
    /// LP token address, and LP token amount to be added.
    function addLpTokensInternal(
        LiquidityMiningTypes.UpdateLpToken[] memory updateLpToken
    ) external;

    /// @notice Adds Power tokens to the liquidity mining for multiple accounts.
    /// @param updatePwToken An array of `UpdatePwToken` structures, each containing the account address,
    /// LP token address, and Power token amount to be added.
    function addPwTokensInternal(
        LiquidityMiningTypes.UpdatePwToken[] memory updatePwToken
    ) external;

    /// @notice Removes LP tokens from the liquidity mining for multiple accounts.
    /// @param updateLpToken An array of `UpdateLpToken` structures, each containing the account address,
    /// LP token address, and LP token amount to be removed.
    function removeLpTokensInternal(
        LiquidityMiningTypes.UpdateLpToken[] memory updateLpToken
    ) external;

    /// @notice Removes Power Tokens from the liquidity mining for multiple accounts.
    /// @param updatePwToken An array of `UpdatePwToken` structures, each containing the account address,
    /// LP token address, and Power Token amount to be removed.
    function removePwTokensInternal(
        LiquidityMiningTypes.UpdatePwToken[] memory updatePwToken
    ) external;

    /// @notice Claims accumulated rewards for multiple LP tokens and transfers them to the specified account.
    /// @param account The account address to claim rewards for.
    /// @param lpTokens An array of LP token addresses for which rewards will be claimed.
    /// @return rewardsAmountToTransfer The total amount of rewards transferred to the account.
    function claimInternal(
        address account,
        address[] calldata lpTokens
    ) external returns (uint256 rewardsAmountToTransfer);

    /// @notice Retrieves the global indicators for multiple LP tokens.
    /// @param lpTokens An array of LP token addresses for which to retrieve the global indicators.
    /// @return An array of LiquidityMiningTypes.GlobalIndicatorsResult containing the global indicators for each LP token.
    function getGlobalIndicators(
        address[] calldata lpTokens
    ) external view returns (LiquidityMiningTypes.GlobalIndicatorsResult[] memory);

    /// @notice Retrieves the account indicators for a specific account and multiple LP tokens.
    /// @param account The address of the account for which to retrieve the account indicators.
    /// @param lpTokens An array of LP token addresses for which to retrieve the account indicators.
    /// @return An array of LiquidityMiningTypes.AccountIndicatorsResult containing the account indicators for each LP token.
    function getAccountIndicators(
        address account,
        address[] calldata lpTokens
    ) external view returns (LiquidityMiningTypes.AccountIndicatorsResult[] memory);

    /// @notice Emitted when the account claims the rewards
    /// @param account Account's address in the context of which activities of claiming are performed
    /// @param lpTokens The addresses of the lpTokens for which the rewards are claimed
    /// @param rewardsAmount Reward amount denominated in pwToken, represented with 18 decimals
    event Claimed(address account, address[] lpTokens, uint256 rewardsAmount);

    /// @notice Emitted when update was triggered for the account on the lpToken
    /// @param account Account address to which the update was triggered
    /// @param lpToken lpToken address to which the update was triggered
    event IndicatorsUpdated(address account, address lpToken);

    /// @notice Emitted when the lpToken is added to the LiquidityMining
    /// @param beneficiary Account address on behalf of which the lpToken is added
    /// @param lpToken lpToken address which is added
    /// @param lpTokenAmount Amount of lpTokens added, represented with 18 decimals
    event LpTokenAdded(address beneficiary, address lpToken, uint256 lpTokenAmount);

    /// @notice Emitted when the lpToken is removed from the LiquidityMining
    /// @param account address on behalf of which the lpToken is removed
    /// @param lpToken lpToken address which is removed
    /// @param lpTokenAmount Amount of lpTokens removed, represented with 18 decimals
    event LpTokensRemoved(address account, address lpToken, uint256 lpTokenAmount);

    /// @notice Emitted when the PwTokens is added to lpToken pool
    /// @param beneficiary Account address on behalf of which the PwToken is added
    /// @param lpToken lpToken address to which the PwToken is added
    /// @param pwTokenAmount Amount of PwTokens added, represented with 18 decimals
    event PwTokensAdded(address beneficiary, address lpToken, uint256 pwTokenAmount);

    /// @notice Emitted when the PwTokens is removed from lpToken pool
    /// @param account Account address on behalf of which the PwToken is removed
    /// @param lpToken lpToken address from which the PwToken is removed
    /// @param pwTokenAmount Amount of PwTokens removed, represented with 18 decimals
    event PwTokensRemoved(address account, address lpToken, uint256 pwTokenAmount);
}

/// @title Struct used across Liquidity Mining.
library PowerTokenTypes {
    struct PwTokenCooldown {
        // @dev The timestamp when the account can redeem Power Tokens
        uint256 endTimestamp;
        // @dev The amount of Power Tokens which can be redeemed without fee when the cooldown reaches `endTimestamp`
        uint256 pwTokenAmount;
    }

    struct UpdateGovernanceToken {
        address beneficiary;
        uint256 governanceTokenAmount;
    }
}

/// @title The Interface for the interaction with the PowerToken - smart contract responsible
/// for managing Power Token (pwToken), Swapping Staked Token for Power Tokens, and
/// delegating Power Tokens to other components.
interface IPowerToken {
    /// @notice Gets the name of the Power Token
    /// @return Returns the name of the Power Token.
    function name() external pure returns (string memory);

    /// @notice Contract ID. The keccak-256 hash of "io.ipor.PowerToken" decreased by 1
    /// @return Returns the ID of the contract
    function getContractId() external pure returns (bytes32);

    /// @notice Gets the symbol of the Power Token.
    /// @return Returns the symbol of the Power Token.
    function symbol() external pure returns (string memory);

    /// @notice Returns the number of the decimals used by Power Token. By default it's 18 decimals.
    /// @return Returns the number of decimals: 18.
    function decimals() external pure returns (uint8);

    /// @notice Gets the total supply of the Power Token.
    /// @dev Value is calculated in runtime using baseTotalSupply and internal exchange rate.
    /// @return Total supply of Power tokens, represented with 18 decimals
    function totalSupply() external view returns (uint256);

    /// @notice Gets the balance of Power Tokens for a given account
    /// @param account account address for which the balance of Power Tokens is fetched
    /// @return Returns the amount of the Power Tokens owned by the `account`.
    function balanceOf(address account) external view returns (uint256);

    /// @notice Gets the delegated balance of the Power Tokens for a given account.
    /// Tokens are delegated from PowerToken to LiquidityMining smart contract (reponsible for rewards distribution).
    /// @param account account address for which the balance of delegated Power Tokens is checked
    /// @return  Returns the amount of the Power Tokens owned by the `account` and delegated to the LiquidityMining contracts.
    function delegatedToLiquidityMiningBalanceOf(address account) external view returns (uint256);

    /// @notice Gets the rate of the fee from the configuration. This fee is applied when the owner of Power Tokens wants to unstake them immediately.
    /// @dev Fee value represented in as a percentage with 18 decimals
    /// @return value, a percentage represented with 18 decimal
    function getUnstakeWithoutCooldownFee() external view returns (uint256);

    /// @notice Gets the state of the active cooldown for the sender.
    /// @dev If PowerTokenTypes.PowerTokenCoolDown contains only zeros it represents no active cool down.
    /// Struct containing information on when the cooldown end and what is the quantity of the Power Tokens locked.
    /// @param account account address that owns Power Tokens in the cooldown
    /// @return Object PowerTokenTypes.PowerTokenCoolDown represents active cool down
    function getActiveCooldown(
        address account
    ) external view returns (PowerTokenTypes.PwTokenCooldown memory);

    /// @notice Initiates a cooldown for the specified account.
    /// @dev This function allows an account to initiate a cooldown period for a specified amount of Power Tokens.
    ///      During the cooldown period, the specified amount of Power Tokens cannot be redeemed or transferred.
    /// @param account The account address for which the cooldown is initiated.
    /// @param pwTokenAmount The amount of Power Tokens to be put on cooldown.
    function cooldownInternal(address account, uint256 pwTokenAmount) external;

    /// @notice Cancels the cooldown for the specified account.
    /// @dev This function allows an account to cancel the active cooldown period for their Power Tokens,
    ///      enabling them to freely redeem or transfer their Power Tokens.
    /// @param account The account address for which the cooldown is to be canceled.
    function cancelCooldownInternal(address account) external;

    /// @notice Redeems Power Tokens for the specified account.
    /// @dev This function allows an account to redeem their Power Tokens, transferring the specified
    ///      amount of Power Tokens back to the account's staked token balance.
    ///      The redemption is subject to the cooldown period, and the account must wait for the cooldown
    ///      period to finish before being able to redeem the Power Tokens.
    /// @param account The account address for which Power Tokens are to be redeemed.
    /// @return transferAmount The amount of Power Tokens that have been redeemed and transferred back to the staked token balance.
    function redeemInternal(address account) external returns (uint256 transferAmount);

    /// @notice Adds staked tokens to the specified account.
    /// @dev This function allows the specified account to add staked tokens to their Power Token balance.
    ///      The staked tokens are converted to Power Tokens based on the internal exchange rate.
    /// @param updateGovernanceToken An object of type PowerTokenTypes.UpdateGovernanceToken containing the details of the staked token update.
    function addGovernanceTokenInternal(
        PowerTokenTypes.UpdateGovernanceToken memory updateGovernanceToken
    ) external;

    /// @notice Removes staked tokens from the specified account, applying a fee.
    /// @dev This function allows the specified account to remove staked tokens from their Power Token balance,
    ///      while deducting a fee from the staked token amount. The fee is determined based on the cooldown period.
    /// @param updateGovernanceToken An object of type PowerTokenTypes.UpdateGovernanceToken containing the details of the staked token update.
    /// @return governanceTokenAmountToTransfer The amount of staked tokens to be transferred after applying the fee.
    function removeGovernanceTokenWithFeeInternal(
        PowerTokenTypes.UpdateGovernanceToken memory updateGovernanceToken
    ) external returns (uint256 governanceTokenAmountToTransfer);

    /// @notice Delegates a specified amount of Power Tokens from the caller's balance to the Liquidity Mining contract.
    /// @dev This function allows the caller to delegate a specified amount of Power Tokens to the Liquidity Mining contract,
    ///      enabling them to participate in liquidity mining and earn rewards.
    /// @param account The address of the account delegating the Power Tokens.
    /// @param pwTokenAmount The amount of Power Tokens to delegate.
    function delegateInternal(address account, uint256 pwTokenAmount) external;

    /// @notice Undelegated a specified amount of Power Tokens from the Liquidity Mining contract back to the caller's balance.
    /// @dev This function allows the caller to undelegate a specified amount of Power Tokens from the Liquidity Mining contract,
    ///      effectively removing them from participation in liquidity mining and stopping the earning of rewards.
    /// @param account The address of the account to undelegate the Power Tokens from.
    /// @param pwTokenAmount The amount of Power Tokens to undelegate.
    function undelegateInternal(address account, uint256 pwTokenAmount) external;

    /// @notice Emitted when the account stake/add [Staked] Tokens
    /// @param account account address that executed the staking
    /// @param governanceTokenAmount of Staked Token amount being staked into PowerToken contract
    /// @param internalExchangeRate internal exchange rate used to calculate the base amount
    /// @param baseAmount value calculated based on the governanceTokenAmount and the internalExchangeRate
    event GovernanceTokenAdded(
        address indexed account,
        uint256 governanceTokenAmount,
        uint256 internalExchangeRate,
        uint256 baseAmount
    );

    /// @notice Emitted when the account unstakes the Power Tokens
    /// @param account address that executed the unstaking
    /// @param pwTokenAmount amount of Power Tokens that were unstaked
    /// @param internalExchangeRate which was used to calculate the base amount
    /// @param fee amount subtracted from the pwTokenAmount
    event GovernanceTokenRemovedWithFee(
        address indexed account,
        uint256 pwTokenAmount,
        uint256 internalExchangeRate,
        uint256 fee
    );

    /// @notice Emitted when the sender delegates the Power Tokens to the LiquidityMining contract
    /// @param account address delegating the Power Tokens
    /// @param pwTokenAmounts amounts of Power Tokens delegated to respective lpTokens
    event Delegated(address indexed account, uint256 pwTokenAmounts);

    /// @notice Emitted when the sender undelegates Power Tokens from the LiquidityMining
    /// @param account address undelegating Power Tokens
    /// @param pwTokenAmounts amounts of Power Tokens undelegated form respective lpTokens
    event Undelegated(address indexed account, uint256 pwTokenAmounts);

    /// @notice Emitted when the sender sets the cooldown on Power Tokens
    /// @param pwTokenAmount amount of pwToken in cooldown
    /// @param endTimestamp end time of the cooldown
    event CooldownChanged(uint256 pwTokenAmount, uint256 endTimestamp);

    /// @notice Emitted when the sender redeems the pwTokens after the cooldown
    /// @param account address that executed the redeem function
    /// @param pwTokenAmount amount of the pwTokens that was transferred to the Power Token owner's address
    event Redeem(address indexed account, uint256 pwTokenAmount);
}

library Errors {
    /// @notice Error thrown when the lpToken address is not supported
    /// @dev List of supported LpTokens is defined in {LiquidityMining._lpTokens}
    string public constant LP_TOKEN_NOT_SUPPORTED = "PT_701";
    /// @notice Error thrown when the caller / msgSender is not a Pause Manager address.
    /// @dev Pause Manager can be defined by the smart contract's Onwer
    string public constant CALLER_NOT_PAUSE_MANAGER = "PT_704";
    /// @notice Error thrown when the account's base balance is too low
    string public constant ACCOUNT_BASE_BALANCE_IS_TOO_LOW = "PT_705";
    /// @notice Error thrown when the account's Lp Token balance is too low
    string public constant ACCOUNT_LP_TOKEN_BALANCE_IS_TOO_LOW = "PT_706";
    /// @notice Error thrown when the account's delegated balance is too low
    string public constant ACC_DELEGATED_TO_LIQUIDITY_MINING_BALANCE_IS_TOO_LOW = "PT_707";
    /// @notice Error thrown when the account's available Power Token balance is too low
    string public constant ACC_AVAILABLE_POWER_TOKEN_BALANCE_IS_TOO_LOW = "PT_708";
    /// @notice Error thrown when the account doesn't have the rewards (Staked Tokens / Power Tokens) to claim
    string public constant NO_REWARDS_TO_CLAIM = "PT_709";
    /// @notice Error thrown when the cooldown is not finished.
    string public constant COOL_DOWN_NOT_FINISH = "PT_710";
    /// @notice Error thrown when the aggregate power up indicator is going to be negative during the calculation.
    string public constant AGGREGATE_POWER_UP_COULD_NOT_BE_NEGATIVE = "PT_711";
    /// @notice Error thrown when the block number used in the function is lower than previous block number stored in the liquidity mining indicators.
    string public constant BLOCK_NUMBER_LOWER_THAN_PREVIOUS_BLOCK_NUMBER = "PT_712";
    /// @notice Account Composite Multiplier indicator is greater or equal to Composit Multiplier indicator, but it should be lower or equal
    string public constant ACCOUNT_COMPOSITE_MULTIPLIER_GT_COMPOSITE_MULTIPLIER = "PT_713";
    /// @notice The fee for unstacking of Power Tokens should be number between (0, 1e18)
    string public constant UNSTAKE_WITHOUT_COOLDOWN_FEE_IS_TO_HIGH = "PT_714";
    /// @notice General problem, address is wrong
    string public constant WRONG_ADDRESS = "PT_715";
    /// @notice General problem, contract is wrong
    string public constant WRONG_CONTRACT_ID = "PT_716";
    /// @notice Value not greater than zero
    string public constant VALUE_NOT_GREATER_THAN_ZERO = "PT_717";
    /// @notice Appeared when input of two arrays length mismatch
    string public constant INPUT_ARRAYS_LENGTH_MISMATCH = "PT_718";
    /// @notice msg.sender is not an appointed owner, it cannot confirm their ownership
    string public constant SENDER_NOT_APPOINTED_OWNER = "PT_719";
    /// @notice msg.sender is not an appointed owner, it cannot confirm their ownership
    string public constant ROUTER_INVALID_SIGNATURE = "PT_720";
    string public constant INPUT_ARRAYS_EMPTY = "PT_721";
    string public constant CALLER_NOT_ROUTER = "PT_722";
    string public constant CALLER_NOT_GUARDIAN = "PT_723";
    string public constant CONTRACT_PAUSED = "PT_724";
    string public constant REENTRANCY = "PT_725";
    string public constant CALLER_NOT_OWNER = "PT_726";
}

library ContractValidator {
    function checkAddress(address addr) internal pure returns (address) {
        require(addr != address(0), Errors.WRONG_ADDRESS);
        return addr;
    }
}

/// @dev It is not recommended to use service contract directly, should be used only through router (like IporProtocolRouter or PowerTokenRouter)
contract FlowsService is IPowerTokenFlowsService {
    using ContractValidator for address;
    using SafeERC20 for IERC20;
    address public immutable liquidityMining;
    address public immutable powerToken;
    address public immutable governanceToken;

    constructor(
        address liquidityMiningInput,
        address governanceTokenInput,
        address powerTokenInput
    ) {
        liquidityMining = liquidityMiningInput.checkAddress();
        governanceToken = governanceTokenInput.checkAddress();
        powerToken = powerTokenInput.checkAddress();
    }

    function getConfiguration() external view returns (address, address, address) {
        return (liquidityMining, powerToken, governanceToken);
    }

    function claimRewardsFromLiquidityMining(address[] calldata lpTokens) external {
        require(lpTokens.length > 0, Errors.INPUT_ARRAYS_EMPTY);
        uint256 rewardsAmountToTransfer = ILiquidityMining(liquidityMining).claimInternal(
            msg.sender,
            lpTokens
        );
        require(rewardsAmountToTransfer > 0, Errors.NO_REWARDS_TO_CLAIM);
        IPowerToken(powerToken).addGovernanceTokenInternal(
            PowerTokenTypes.UpdateGovernanceToken(msg.sender, rewardsAmountToTransfer)
        );
        IERC20(governanceToken).safeTransferFrom(
            liquidityMining,
            powerToken,
            rewardsAmountToTransfer
        );
    }

    function updateIndicatorsInLiquidityMining(
        address account,
        address[] calldata lpTokens
    ) external {
        require(lpTokens.length > 0, Errors.INPUT_ARRAYS_EMPTY);
        ILiquidityMining(liquidityMining).updateIndicators(account, lpTokens);
    }

    function delegatePwTokensToLiquidityMining(
        address[] calldata lpTokens,
        uint256[] calldata pwTokenAmounts
    ) external {
        uint256 lpTokensLength = lpTokens.length;
        require(lpTokensLength == pwTokenAmounts.length, Errors.INPUT_ARRAYS_LENGTH_MISMATCH);
        require(lpTokensLength > 0, Errors.INPUT_ARRAYS_EMPTY);
        uint256 totalGovernanceTokenAmount;
        address account = msg.sender;
        LiquidityMiningTypes.UpdatePwToken[]
            memory updatePwTokens = new LiquidityMiningTypes.UpdatePwToken[](lpTokensLength);
        for (uint256 i; i != lpTokensLength; ) {
            totalGovernanceTokenAmount += pwTokenAmounts[i];
            updatePwTokens[i] = LiquidityMiningTypes.UpdatePwToken(
                account,
                lpTokens[i],
                pwTokenAmounts[i]
            );
            unchecked {
                ++i;
            }
        }
        IPowerToken(powerToken).delegateInternal(account, totalGovernanceTokenAmount);
        ILiquidityMining(liquidityMining).addPwTokensInternal(updatePwTokens);
    }

    function undelegatePwTokensFromLiquidityMining(
        address[] calldata lpTokens,
        uint256[] calldata pwTokenAmounts
    ) external {
        uint256 length = lpTokens.length;
        require(length == pwTokenAmounts.length, Errors.INPUT_ARRAYS_LENGTH_MISMATCH);
        require(length > 0, Errors.INPUT_ARRAYS_EMPTY);
        uint256 totalGovernanceTokenAmount;
        address account = msg.sender;
        LiquidityMiningTypes.UpdatePwToken[]
            memory updatePwTokens = new LiquidityMiningTypes.UpdatePwToken[](length);
        for (uint256 i; i != length; ) {
            totalGovernanceTokenAmount += pwTokenAmounts[i];
            updatePwTokens[i] = LiquidityMiningTypes.UpdatePwToken(
                account,
                lpTokens[i],
                pwTokenAmounts[i]
            );
            unchecked {
                ++i;
            }
        }
        require(totalGovernanceTokenAmount > 0, Errors.VALUE_NOT_GREATER_THAN_ZERO);
        ILiquidityMining(liquidityMining).removePwTokensInternal(updatePwTokens);
        IPowerToken(powerToken).undelegateInternal(account, totalGovernanceTokenAmount);
    }
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"liquidityMiningInput","type":"address"},{"internalType":"address","name":"governanceTokenInput","type":"address"},{"internalType":"address","name":"powerTokenInput","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address[]","name":"lpTokens","type":"address[]"}],"name":"claimRewardsFromLiquidityMining","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"lpTokens","type":"address[]"},{"internalType":"uint256[]","name":"pwTokenAmounts","type":"uint256[]"}],"name":"delegatePwTokensToLiquidityMining","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getConfiguration","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityMining","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"powerToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"lpTokens","type":"address[]"},{"internalType":"uint256[]","name":"pwTokenAmounts","type":"uint256[]"}],"name":"undelegatePwTokensFromLiquidityMining","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address[]","name":"lpTokens","type":"address[]"}],"name":"updateIndicatorsInLiquidityMining","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60e06040523480156200001157600080fd5b50604051620017773803806200177783398101604081905262000034916200010b565b620000486001600160a01b03841662000094565b6001600160a01b039081166080526200006390831662000094565b6001600160a01b0390811660c0526200007e90821662000094565b6001600160a01b031660a05250620001a5915050565b60408051808201909152600681526550545f37313560d01b60208201526000906001600160a01b038316620000e75760405162461bcd60e51b8152600401620000de919062000155565b60405180910390fd5b5090919050565b80516001600160a01b03811681146200010657600080fd5b919050565b6000806000606084860312156200012157600080fd5b6200012c84620000ee565b92506200013c60208501620000ee565b91506200014c60408501620000ee565b90509250925092565b600060208083528351808285015260005b81811015620001845785810183015185820160400152820162000166565b506000604082860101526040601f19601f8301168501019250505092915050565b60805160a05160c0516115496200022e6000396000818161010a015281816101ef015261094201526000818160e2015281816101b5015281816105c2015281816108ca015281816109870152610d4e01526000818160bd01528181610169015281816102c40152818161065901528181610779015281816109660152610c9d01526115496000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806385b2d5351161005b57806385b2d535146101645780639662ac58146101b0578063ce65e122146101d7578063f96dae0a146101ea57600080fd5b806324afd7881461008d5780636bd50cef146100a2578063724382891461013e5780637c599a2914610151575b600080fd5b6100a061009b3660046111ad565b610211565b005b6040805173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811682527f0000000000000000000000000000000000000000000000000000000000000000811660208301527f000000000000000000000000000000000000000000000000000000000000000016918101919091526060015b60405180910390f35b6100a061014c366004611200565b610334565b6100a061015f36600461126c565b6106cc565b61018b7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610135565b61018b7f000000000000000000000000000000000000000000000000000000000000000081565b6100a06101e5366004611200565b6109b1565b61018b7f000000000000000000000000000000000000000000000000000000000000000081565b60408051808201909152600681527f50545f3732310000000000000000000000000000000000000000000000000000602082015281610286576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b60405180910390fd5b506040517ffbb0b2b900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063fbb0b2b9906102fd90869086908690600401611323565b600060405180830381600087803b15801561031757600080fd5b505af115801561032b573d6000803e3d6000fd5b50505050505050565b60408051808201909152600681527f50545f3731380000000000000000000000000000000000000000000000000000602082015283908282146103a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b5060408051808201909152600681527f50545f3732310000000000000000000000000000000000000000000000000000602082015281610411576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b50600033818367ffffffffffffffff81111561042f5761042f61138a565b60405190808252806020026020018201604052801561049857816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161044d5790505b50905060005b848114610575578686828181106104b7576104b76113b9565b90506020020135846104c991906113e8565b935060405180606001604052808473ffffffffffffffffffffffffffffffffffffffff1681526020018a8a84818110610504576105046113b9565b90506020020160208101906105199190611428565b73ffffffffffffffffffffffffffffffffffffffff168152602001888884818110610546576105466113b9565b90506020020135815250828281518110610562576105626113b9565b602090810291909101015260010161049e565b506040517f84074b1500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018590527f000000000000000000000000000000000000000000000000000000000000000016906384074b1590604401600060405180830381600087803b15801561060657600080fd5b505af115801561061a573d6000803e3d6000fd5b50506040517fa020202a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016925063a020202a915061069090849060040161144a565b600060405180830381600087803b1580156106aa57600080fd5b505af11580156106be573d6000803e3d6000fd5b505050505050505050505050565b60408051808201909152600681527f50545f3732310000000000000000000000000000000000000000000000000000602082015281610738576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b506040517f82fe84ab00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906382fe84ab906107b290339087908790600401611323565b6020604051808303816000875af11580156107d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f591906114bc565b9050600081116040518060400160405280600681526020017f50545f373039000000000000000000000000000000000000000000000000000081525090610869576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b506040805180820182523381526020810183815291517fdc94b4a1000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9081166004830152915160248201527f00000000000000000000000000000000000000000000000000000000000000009091169063dc94b4a190604401600060405180830381600087803b15801561091057600080fd5b505af1158015610924573d6000803e3d6000fd5b506109ac92505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084610d7f565b505050565b60408051808201909152600681527f50545f373138000000000000000000000000000000000000000000000000000060208201528390828214610a21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b5060408051808201909152600681527f50545f3732310000000000000000000000000000000000000000000000000000602082015281610a8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b50600033818367ffffffffffffffff811115610aac57610aac61138a565b604051908082528060200260200182016040528015610b1557816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610aca5790505b50905060005b848114610bf257868682818110610b3457610b346113b9565b9050602002013584610b4691906113e8565b935060405180606001604052808473ffffffffffffffffffffffffffffffffffffffff1681526020018a8a84818110610b8157610b816113b9565b9050602002016020810190610b969190611428565b73ffffffffffffffffffffffffffffffffffffffff168152602001888884818110610bc357610bc36113b9565b90506020020135815250828281518110610bdf57610bdf6113b9565b6020908102919091010152600101610b1b565b5060408051808201909152600681527f50545f3731370000000000000000000000000000000000000000000000000000602082015283610c5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b506040517f778170ba00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063778170ba90610cd290849060040161144a565b600060405180830381600087803b158015610cec57600080fd5b505af1158015610d00573d6000803e3d6000fd5b50506040517f706fde1100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018790527f000000000000000000000000000000000000000000000000000000000000000016925063706fde119150604401610690565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052610e14908590610e1a565b50505050565b6000610e7c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16610f299092919063ffffffff16565b9050805160001480610e9d575080806020019051810190610e9d91906114d5565b6109ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161027d565b6060610f388484600085610f40565b949350505050565b606082471015610fd2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161027d565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610ffb91906114f7565b60006040518083038185875af1925050503d8060008114611038576040519150601f19603f3d011682016040523d82523d6000602084013e61103d565b606091505b509150915061104e87838387611059565b979650505050505050565b606083156110ef5782516000036110e85773ffffffffffffffffffffffffffffffffffffffff85163b6110e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161027d565b5081610f38565b610f3883838151156111045781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b803573ffffffffffffffffffffffffffffffffffffffff8116811461115c57600080fd5b919050565b60008083601f84011261117357600080fd5b50813567ffffffffffffffff81111561118b57600080fd5b6020830191508360208260051b85010111156111a657600080fd5b9250929050565b6000806000604084860312156111c257600080fd5b6111cb84611138565b9250602084013567ffffffffffffffff8111156111e757600080fd5b6111f386828701611161565b9497909650939450505050565b6000806000806040858703121561121657600080fd5b843567ffffffffffffffff8082111561122e57600080fd5b61123a88838901611161565b9096509450602087013591508082111561125357600080fd5b5061126087828801611161565b95989497509550505050565b6000806020838503121561127f57600080fd5b823567ffffffffffffffff81111561129657600080fd5b6112a285828601611161565b90969095509350505050565b60005b838110156112c95781810151838201526020016112b1565b50506000910152565b60208152600082518060208401526112f18160408501602087016112ae565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff848116825260406020808401829052908301849052600091859160608501845b8781101561137d578361136a86611138565b1682529382019390820190600101611358565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80820180821115611422577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b60006020828403121561143a57600080fd5b61144382611138565b9392505050565b602080825282518282018190526000919060409081850190868401855b828110156114af578151805173ffffffffffffffffffffffffffffffffffffffff90811686528782015116878601528501518585015260609093019290850190600101611467565b5091979650505050505050565b6000602082840312156114ce57600080fd5b5051919050565b6000602082840312156114e757600080fd5b8151801515811461144357600080fd5b600082516115098184602087016112ae565b919091019291505056fea264697066735822122058b3e30ebaaa01440c4b25125417905e58a2ad89b2d66cbc8ec06600e7d244ae64736f6c63430008140033000000000000000000000000de645ab0560e5a413820234d9dded5f4a55ff6dd00000000000000000000000034229b3f16fbcdfa8d8d9d17c0852f9496f4c7bb00000000000000000000000021f1209692ed441664183413f2fdd675adb3223b

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100885760003560e01c806385b2d5351161005b57806385b2d535146101645780639662ac58146101b0578063ce65e122146101d7578063f96dae0a146101ea57600080fd5b806324afd7881461008d5780636bd50cef146100a2578063724382891461013e5780637c599a2914610151575b600080fd5b6100a061009b3660046111ad565b610211565b005b6040805173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000de645ab0560e5a413820234d9dded5f4a55ff6dd811682527f00000000000000000000000021f1209692ed441664183413f2fdd675adb3223b811660208301527f00000000000000000000000034229b3f16fbcdfa8d8d9d17c0852f9496f4c7bb16918101919091526060015b60405180910390f35b6100a061014c366004611200565b610334565b6100a061015f36600461126c565b6106cc565b61018b7f000000000000000000000000de645ab0560e5a413820234d9dded5f4a55ff6dd81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610135565b61018b7f00000000000000000000000021f1209692ed441664183413f2fdd675adb3223b81565b6100a06101e5366004611200565b6109b1565b61018b7f00000000000000000000000034229b3f16fbcdfa8d8d9d17c0852f9496f4c7bb81565b60408051808201909152600681527f50545f3732310000000000000000000000000000000000000000000000000000602082015281610286576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b60405180910390fd5b506040517ffbb0b2b900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000de645ab0560e5a413820234d9dded5f4a55ff6dd169063fbb0b2b9906102fd90869086908690600401611323565b600060405180830381600087803b15801561031757600080fd5b505af115801561032b573d6000803e3d6000fd5b50505050505050565b60408051808201909152600681527f50545f3731380000000000000000000000000000000000000000000000000000602082015283908282146103a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b5060408051808201909152600681527f50545f3732310000000000000000000000000000000000000000000000000000602082015281610411576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b50600033818367ffffffffffffffff81111561042f5761042f61138a565b60405190808252806020026020018201604052801561049857816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161044d5790505b50905060005b848114610575578686828181106104b7576104b76113b9565b90506020020135846104c991906113e8565b935060405180606001604052808473ffffffffffffffffffffffffffffffffffffffff1681526020018a8a84818110610504576105046113b9565b90506020020160208101906105199190611428565b73ffffffffffffffffffffffffffffffffffffffff168152602001888884818110610546576105466113b9565b90506020020135815250828281518110610562576105626113b9565b602090810291909101015260010161049e565b506040517f84074b1500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018590527f00000000000000000000000021f1209692ed441664183413f2fdd675adb3223b16906384074b1590604401600060405180830381600087803b15801561060657600080fd5b505af115801561061a573d6000803e3d6000fd5b50506040517fa020202a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000de645ab0560e5a413820234d9dded5f4a55ff6dd16925063a020202a915061069090849060040161144a565b600060405180830381600087803b1580156106aa57600080fd5b505af11580156106be573d6000803e3d6000fd5b505050505050505050505050565b60408051808201909152600681527f50545f3732310000000000000000000000000000000000000000000000000000602082015281610738576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b506040517f82fe84ab00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000de645ab0560e5a413820234d9dded5f4a55ff6dd16906382fe84ab906107b290339087908790600401611323565b6020604051808303816000875af11580156107d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f591906114bc565b9050600081116040518060400160405280600681526020017f50545f373039000000000000000000000000000000000000000000000000000081525090610869576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b506040805180820182523381526020810183815291517fdc94b4a1000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9081166004830152915160248201527f00000000000000000000000021f1209692ed441664183413f2fdd675adb3223b9091169063dc94b4a190604401600060405180830381600087803b15801561091057600080fd5b505af1158015610924573d6000803e3d6000fd5b506109ac92505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000034229b3f16fbcdfa8d8d9d17c0852f9496f4c7bb1690507f000000000000000000000000de645ab0560e5a413820234d9dded5f4a55ff6dd7f00000000000000000000000021f1209692ed441664183413f2fdd675adb3223b84610d7f565b505050565b60408051808201909152600681527f50545f373138000000000000000000000000000000000000000000000000000060208201528390828214610a21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b5060408051808201909152600681527f50545f3732310000000000000000000000000000000000000000000000000000602082015281610a8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b50600033818367ffffffffffffffff811115610aac57610aac61138a565b604051908082528060200260200182016040528015610b1557816020015b60408051606081018252600080825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610aca5790505b50905060005b848114610bf257868682818110610b3457610b346113b9565b9050602002013584610b4691906113e8565b935060405180606001604052808473ffffffffffffffffffffffffffffffffffffffff1681526020018a8a84818110610b8157610b816113b9565b9050602002016020810190610b969190611428565b73ffffffffffffffffffffffffffffffffffffffff168152602001888884818110610bc357610bc36113b9565b90506020020135815250828281518110610bdf57610bdf6113b9565b6020908102919091010152600101610b1b565b5060408051808201909152600681527f50545f3731370000000000000000000000000000000000000000000000000000602082015283610c5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b506040517f778170ba00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000de645ab0560e5a413820234d9dded5f4a55ff6dd169063778170ba90610cd290849060040161144a565b600060405180830381600087803b158015610cec57600080fd5b505af1158015610d00573d6000803e3d6000fd5b50506040517f706fde1100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018790527f00000000000000000000000021f1209692ed441664183413f2fdd675adb3223b16925063706fde119150604401610690565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052610e14908590610e1a565b50505050565b6000610e7c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16610f299092919063ffffffff16565b9050805160001480610e9d575080806020019051810190610e9d91906114d5565b6109ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161027d565b6060610f388484600085610f40565b949350505050565b606082471015610fd2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161027d565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610ffb91906114f7565b60006040518083038185875af1925050503d8060008114611038576040519150601f19603f3d011682016040523d82523d6000602084013e61103d565b606091505b509150915061104e87838387611059565b979650505050505050565b606083156110ef5782516000036110e85773ffffffffffffffffffffffffffffffffffffffff85163b6110e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161027d565b5081610f38565b610f3883838151156111045781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027d91906112d2565b803573ffffffffffffffffffffffffffffffffffffffff8116811461115c57600080fd5b919050565b60008083601f84011261117357600080fd5b50813567ffffffffffffffff81111561118b57600080fd5b6020830191508360208260051b85010111156111a657600080fd5b9250929050565b6000806000604084860312156111c257600080fd5b6111cb84611138565b9250602084013567ffffffffffffffff8111156111e757600080fd5b6111f386828701611161565b9497909650939450505050565b6000806000806040858703121561121657600080fd5b843567ffffffffffffffff8082111561122e57600080fd5b61123a88838901611161565b9096509450602087013591508082111561125357600080fd5b5061126087828801611161565b95989497509550505050565b6000806020838503121561127f57600080fd5b823567ffffffffffffffff81111561129657600080fd5b6112a285828601611161565b90969095509350505050565b60005b838110156112c95781810151838201526020016112b1565b50506000910152565b60208152600082518060208401526112f18160408501602087016112ae565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff848116825260406020808401829052908301849052600091859160608501845b8781101561137d578361136a86611138565b1682529382019390820190600101611358565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80820180821115611422577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b60006020828403121561143a57600080fd5b61144382611138565b9392505050565b602080825282518282018190526000919060409081850190868401855b828110156114af578151805173ffffffffffffffffffffffffffffffffffffffff90811686528782015116878601528501518585015260609093019290850190600101611467565b5091979650505050505050565b6000602082840312156114ce57600080fd5b5051919050565b6000602082840312156114e757600080fd5b8151801515811461144357600080fd5b600082516115098184602087016112ae565b919091019291505056fea264697066735822122058b3e30ebaaa01440c4b25125417905e58a2ad89b2d66cbc8ec06600e7d244ae64736f6c63430008140033

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

000000000000000000000000de645ab0560e5a413820234d9dded5f4a55ff6dd00000000000000000000000034229b3f16fbcdfa8d8d9d17c0852f9496f4c7bb00000000000000000000000021f1209692ed441664183413f2fdd675adb3223b

-----Decoded View---------------
Arg [0] : liquidityMiningInput (address): 0xdE645aB0560E5A413820234d9DDED5f4a55Ff6dd
Arg [1] : governanceTokenInput (address): 0x34229B3f16fBCDfA8d8d9d17C0852F9496f4C7BB
Arg [2] : powerTokenInput (address): 0x21f1209692eD441664183413F2fdd675adb3223b

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000de645ab0560e5a413820234d9dded5f4a55ff6dd
Arg [1] : 00000000000000000000000034229b3f16fbcdfa8d8d9d17c0852f9496f4c7bb
Arg [2] : 00000000000000000000000021f1209692ed441664183413f2fdd675adb3223b


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.