MON Price: $0.018737 (+2.28%)

Contract

0x7Fbf96c38fAd9baF4992497544a7B274310D7798

Overview

MON Balance

Monad Chain LogoMonad Chain LogoMonad Chain Logo655.171760180860830342 MON

MON Value

$12.28 (@ $0.02/MON)

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Update Commissio...391603942025-12-01 9:24:5654 days ago1764581096IN
0x7Fbf96c3...4310D7798
0 MON0.00355121102.91
Update Commissio...391596492025-12-01 9:19:5854 days ago1764580798IN
0x7Fbf96c3...4310D7798
0 MON0.00348756101.82064631

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
508050182026-01-24 12:31:003 hrs ago1769257860
0x7Fbf96c3...4310D7798
32.758588 MON
508050182026-01-24 12:31:003 hrs ago1769257860
0x7Fbf96c3...4310D7798
622.41317217 MON
507550172026-01-24 6:57:019 hrs ago1769237821
0x7Fbf96c3...4310D7798
32.758588 MON
507550172026-01-24 6:57:019 hrs ago1769237821
0x7Fbf96c3...4310D7798
622.41317217 MON
507050112026-01-24 1:23:4114 hrs ago1769217821
0x7Fbf96c3...4310D7798
32.758588 MON
507050112026-01-24 1:23:4114 hrs ago1769217821
0x7Fbf96c3...4310D7798
622.41317217 MON
506550032026-01-23 19:50:0520 hrs ago1769197805
0x7Fbf96c3...4310D7798
32.758588 MON
506550032026-01-23 19:50:0520 hrs ago1769197805
0x7Fbf96c3...4310D7798
622.41317217 MON
506050082026-01-23 14:15:4925 hrs ago1769177749
0x7Fbf96c3...4310D7798
32.758588 MON
506050082026-01-23 14:15:4925 hrs ago1769177749
0x7Fbf96c3...4310D7798
622.41317217 MON
505550182026-01-23 8:42:3131 hrs ago1769157751
0x7Fbf96c3...4310D7798
32.758588 MON
505550182026-01-23 8:42:3131 hrs ago1769157751
0x7Fbf96c3...4310D7798
622.41317217 MON
505050092026-01-23 3:08:3636 hrs ago1769137716
0x7Fbf96c3...4310D7798
32.758588 MON
505050092026-01-23 3:08:3636 hrs ago1769137716
0x7Fbf96c3...4310D7798
622.41317217 MON
504550102026-01-22 21:34:5442 hrs ago1769117694
0x7Fbf96c3...4310D7798
32.758588 MON
504550102026-01-22 21:34:5442 hrs ago1769117694
0x7Fbf96c3...4310D7798
622.41317217 MON
504050182026-01-22 16:01:2847 hrs ago1769097688
0x7Fbf96c3...4310D7798
32.758588 MON
504050182026-01-22 16:01:2847 hrs ago1769097688
0x7Fbf96c3...4310D7798
622.41317217 MON
503550092026-01-22 10:27:292 days ago1769077649
0x7Fbf96c3...4310D7798
32.758588 MON
503550092026-01-22 10:27:292 days ago1769077649
0x7Fbf96c3...4310D7798
622.41317217 MON
503050092026-01-22 4:53:382 days ago1769057618
0x7Fbf96c3...4310D7798
32.758588 MON
503050092026-01-22 4:53:382 days ago1769057618
0x7Fbf96c3...4310D7798
622.41317217 MON
502550182026-01-21 23:19:072 days ago1769037547
0x7Fbf96c3...4310D7798
32.758588 MON
502550182026-01-21 23:19:072 days ago1769037547
0x7Fbf96c3...4310D7798
622.41317217 MON
502050162026-01-21 17:45:212 days ago1769017521
0x7Fbf96c3...4310D7798
32.758588 MON
View All Internal Transactions
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x3C1cEa89...f2B34Cc78
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
Coinbase

Compiler Version
v0.8.30+commit.73712a01

Optimization Enabled:
Yes with 50 runs

Other Settings:
cancun EvmVersion, BSL 1.1 license

Contract Source Code (Solidity Standard Json-Input format)

//SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.28 <0.9.0;

import { SafeTransferLib } from "@solady/utils/SafeTransferLib.sol";
import { SafeCastLib } from "@solady/utils/SafeCastLib.sol";

import { IMonadStaking } from "./interfaces/IMonadStaking.sol";
import { ICoinbase } from "./interfaces/ICoinbase.sol";
import {
    STAKING,
    MIN_VALIDATOR_DEPOSIT,
    SCALE,
    TRANSFER_GAS_LIMIT,
    STAKING_GAS_BUFFER,
    STAKING_GAS_EXTERNAL_REWARD,
    STAKING_GAS_GET_VALIDATOR
} from "./Constants.sol";

struct CoinbaseConfig {
    address commissionRecipient; // receives validator commission sent in `process()`
    uint96 commissionRate; // as a fraction of 1e18
}

contract Coinbase is ICoinbase {
    using SafeTransferLib for address;
    using SafeCastLib for uint256;

    uint64 public immutable VAL_ID;
    address public immutable SHMONAD;
    address public immutable AUTH_ADDRESS;
    address public immutable SELF;

    CoinbaseConfig internal s_config;

    error OnlyShMonadCaller();
    error OnlyAuthAddress();
    error OnlySelfCaller();
    error InvalidCommissionRate();
    error CommissionOrRewardFailed();
    error RecipientCannotBeZeroAddress();
    error ValidatorNotFoundInPrecompile(uint64 validatorId);

    event CommissionRateUpdated(uint256 oldCommissionRate, uint256 newCommissionRate);
    event CommissionRecipientUpdated(address oldRecipient, address newRecipient);

    constructor(uint64 valId) {
        VAL_ID = valId;
        SHMONAD = msg.sender;
        SELF = address(this);

        (address _authAddress, uint256 _commissionRate) = _getValidator(valId);

        AUTH_ADDRESS = _authAddress;
        s_config = CoinbaseConfig({ commissionRecipient: _authAddress, commissionRate: _commissionRate.toUint96() });

        emit CommissionRateUpdated(0, _commissionRate);
        emit CommissionRecipientUpdated(address(0), _authAddress);
    }

    receive() external payable { }

    modifier onlyAuthAddress() {
        require(msg.sender == AUTH_ADDRESS, OnlyAuthAddress());
        _;
    }

    modifier onlyShMonad() {
        require(msg.sender == SHMONAD, OnlyShMonadCaller());
        _;
    }

    modifier onlySelf() {
        require(msg.sender == SELF, OnlySelfCaller());
        _;
    }

    /// @dev This is called during `_crankValidator()` in ShMonad, so should never revert.
    function process() external onlyShMonad returns (bool success) {
        CoinbaseConfig memory _config = s_config;

        // Assume all balance is accrued priority fees
        uint256 _currentBalance = address(this).balance;

        // Calculate the commission
        uint256 _validatorCommission = _currentBalance * _config.commissionRate / SCALE;
        uint256 _rewardPortion = _currentBalance - _validatorCommission;

        // Don't pay commission unless the remaining reward is large enough to send via externalReward
        if (_rewardPortion < MIN_VALIDATOR_DEPOSIT) return false;

        // Both commission and rewards must be sent or both should revert
        try this.sendCommissionAndRewards(_config.commissionRecipient, _validatorCommission, _rewardPortion) {
            success = true;
        } catch {
            success = false;
        }
    }

    function sendCommissionAndRewards(
        address commissionRecipient,
        uint256 validatorCommission,
        uint256 rewardPortion
    )
        external
        onlySelf
    {
        bool _sendCommissionSucceeded = true;

        // Send commission to recipient and rewards to staking precompile
        if (validatorCommission > 0) {
            _sendCommissionSucceeded = commissionRecipient.trySafeTransferETH(validatorCommission, TRANSFER_GAS_LIMIT);
        }
        bool _sendRewardsSucceeded = _sendRewards(VAL_ID, rewardPortion);

        // If either of the above sends fail, revert both
        require(_sendCommissionSucceeded && _sendRewardsSucceeded, CommissionOrRewardFailed());
    }

    function updateCommissionRate(uint256 newCommissionRate) external onlyAuthAddress {
        require(newCommissionRate <= SCALE, InvalidCommissionRate());

        uint256 _oldCommissionRate = s_config.commissionRate;
        s_config.commissionRate = newCommissionRate.toUint96();

        emit CommissionRateUpdated(_oldCommissionRate, newCommissionRate);
    }

    function updateCommissionRateFromStakingConfig() external onlyAuthAddress {
        (, uint256 _newCommissionRate) = _getValidator(VAL_ID);

        uint256 _oldCommissionRate = s_config.commissionRate;
        s_config.commissionRate = _newCommissionRate.toUint96();

        emit CommissionRateUpdated(_oldCommissionRate, _newCommissionRate);
    }

    function updateCommissionRecipient(address newRecipient) external onlyAuthAddress {
        require(newRecipient != address(0), RecipientCannotBeZeroAddress());
        address _oldRecipient = s_config.commissionRecipient;
        s_config.commissionRecipient = newRecipient;

        emit CommissionRecipientUpdated(_oldRecipient, newRecipient);
    }

    function getCommissionRate() external view returns (uint256) {
        return s_config.commissionRate;
    }

    function getCommissionRecipient() external view returns (address) {
        return s_config.commissionRecipient;
    }

    function _inEpochDelayPeriod() internal returns (bool) {
        (, bool _isInEpochDelayPeriod) = STAKING.getEpoch();
        return _isInEpochDelayPeriod;
    }

    function _sendRewards(uint64 validatorId, uint256 rewardAmount) internal returns (bool) {
        try STAKING.externalReward{ value: rewardAmount, gas: STAKING_GAS_EXTERNAL_REWARD + STAKING_GAS_BUFFER }(
            validatorId
        ) returns (bool _precompileSuccess) {
            return _precompileSuccess;
        } catch {
            return false;
        }
    }

    function _getValidator(uint64 validatorId) internal returns (address authAddress, uint256 commissionRate) {
        // Note: Real precompile returns zeros for missing, mock reverts with UnknownValidator()
        try STAKING.getValidator{ gas: STAKING_GAS_GET_VALIDATOR + STAKING_GAS_BUFFER }(validatorId) returns (
            address _authAddress,
            uint64,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256 _consensusCommissionRate,
            uint256,
            uint256 _snapshotCommissionRate,
            bytes memory,
            bytes memory
        ) {
            authAddress = _authAddress;
            commissionRate = _inEpochDelayPeriod() ? _snapshotCommissionRate : _consensusCommissionRate;
        } catch { }
        require(authAddress != address(0), ValidatorNotFoundInPrecompile(validatorId));
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @author Permit2 operations from (https://github.com/Uniswap/permit2/blob/main/src/libraries/Permit2Lib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /// @dev The ERC20 `totalSupply` query has failed.
    error TotalSupplyQueryFailed();

    /// @dev The Permit2 operation has failed.
    error Permit2Failed();

    /// @dev The Permit2 amount must be less than `2**160 - 1`.
    error Permit2AmountOverflow();

    /// @dev The Permit2 approve operation has failed.
    error Permit2ApproveFailed();

    /// @dev The Permit2 lockdown operation has failed.
    error Permit2LockdownFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.
    uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;

    /// @dev The unique EIP-712 domain separator for the DAI token contract.
    bytes32 internal constant DAI_DOMAIN_SEPARATOR =
        0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7;

    /// @dev The address for the WETH9 contract on Ethereum mainnet.
    address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

    /// @dev The canonical Permit2 address.
    /// [Github](https://github.com/Uniswap/permit2)
    /// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)
    address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;

    /// @dev The canonical address of the `SELFDESTRUCT` ETH mover.
    /// See: https://gist.github.com/Vectorized/1cb8ad4cf393b1378e08f23f79bd99fa
    /// [Etherscan](https://etherscan.io/address/0x00000000000073c48c8055bD43D1A53799176f0D)
    address internal constant ETH_MOVER = 0x00000000000073c48c8055bD43D1A53799176f0D;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
    //
    // The regular variants:
    // - Forwards all remaining gas to the target.
    // - Reverts if the target reverts.
    // - Reverts if the current contract has insufficient balance.
    //
    // The force variants:
    // - Forwards with an optional gas stipend
    //   (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
    // - If the target reverts, or if the gas stipend is exhausted,
    //   creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
    //   Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
    // - Reverts if the current contract has insufficient balance.
    //
    // The try variants:
    // - Forwards with a mandatory gas stipend.
    // - Instead of reverting, returns whether the transfer succeeded.

    /// @dev Sends `amount` (in wei) ETH to `to`.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`.
    function safeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer all the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // forgefmt: disable-next-item
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function trySafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)
        }
    }

    /// @dev Force transfers ETH to `to`, without triggering the fallback (if any).
    /// This method attempts to use a separate contract to send via `SELFDESTRUCT`,
    /// and upon failure, deploys a minimal vault to accrue the ETH.
    function safeMoveETH(address to, uint256 amount) internal returns (address vault) {
        /// @solidity memory-safe-assembly
        assembly {
            to := shr(96, shl(96, to)) // Clean upper 96 bits.
            for { let mover := ETH_MOVER } iszero(eq(to, address())) {} {
                let selfBalanceBefore := selfbalance()
                if or(lt(selfBalanceBefore, amount), eq(to, mover)) {
                    mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                    revert(0x1c, 0x04)
                }
                if extcodesize(mover) {
                    let balanceBefore := balance(to) // Check via delta, in case `SELFDESTRUCT` is bricked.
                    mstore(0x00, to)
                    pop(call(gas(), mover, amount, 0x00, 0x20, codesize(), 0x00))
                    // If `address(to).balance >= amount + balanceBefore`, skip vault workflow.
                    if iszero(lt(balance(to), add(amount, balanceBefore))) { break }
                    // Just in case `SELFDESTRUCT` is changed to not revert and do nothing.
                    if lt(selfBalanceBefore, selfbalance()) { invalid() }
                }
                let m := mload(0x40)
                // If the mover is missing or bricked, deploy a minimal vault
                // that withdraws all ETH to `to` when being called only by `to`.
                // forgefmt: disable-next-item
                mstore(add(m, 0x20), 0x33146025575b600160005260206000f35b3d3d3d3d47335af1601a5760003dfd)
                mstore(m, or(to, shl(160, 0x6035600b3d3960353df3fe73)))
                // Compute and store the bytecode hash.
                mstore8(0x00, 0xff) // Write the prefix.
                mstore(0x35, keccak256(m, 0x40))
                mstore(0x01, shl(96, address())) // Deployer.
                mstore(0x15, 0) // Salt.
                vault := keccak256(0x00, 0x55)
                pop(call(gas(), vault, amount, codesize(), 0x00, codesize(), 0x00))
                // The vault returns a single word on success. Failure reverts with empty data.
                if iszero(returndatasize()) {
                    if iszero(create2(0, m, 0x40, 0)) { revert(codesize(), codesize()) } // For gas estimation.
                }
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC20 OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    ///
    /// The `from` account must have at least `amount` approved for the current contract to manage.
    function trySafeTransferFrom(address token, address from, address to, uint256 amount)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                success := lt(or(iszero(extcodesize(token)), returndatasize()), success)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends all of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have their entire balance approved for the current contract to manage.
    function safeTransferAllFrom(address token, address from, address to)
        internal
        returns (uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
            amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sends all of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransferAll(address token, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, address()) // Store the address of the current contract.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x14, to) // Store the `to` argument.
            amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
    /// then retries the approval again (some tokens, e.g. USDT, requires this).
    /// Reverts upon failure.
    function safeApproveWithRetry(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, retrying upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x34, 0) // Store 0 for the `amount`.
                    mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
                    pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.
                    mstore(0x34, amount) // Store back the original `amount`.
                    // Retry the approval, reverting upon failure.
                    success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    if iszero(and(eq(mload(0x00), 1), success)) {
                        // Check the `extcodesize` again just in case the token selfdestructs lol.
                        if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                            mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                            revert(0x1c, 0x04)
                        }
                    }
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Returns the amount of ERC20 `token` owned by `account`.
    /// Returns zero if the `token` does not exist.
    function balanceOf(address token, address account) internal view returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            amount :=
                mul( // The arguments of `mul` are evaluated from right to left.
                    mload(0x20),
                    and( // The arguments of `and` are evaluated from right to left.
                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                    )
                )
        }
    }

    /// @dev Performs a `token.balanceOf(account)` check.
    /// `implemented` denotes whether the `token` does not implement `balanceOf`.
    /// `amount` is zero if the `token` does not implement `balanceOf`.
    function checkBalanceOf(address token, address account)
        internal
        view
        returns (bool implemented, uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            implemented :=
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                )
            amount := mul(mload(0x20), implemented)
        }
    }

    /// @dev Returns the total supply of the `token`.
    /// Reverts if the token does not exist or does not implement `totalSupply()`.
    function totalSupply(address token) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x18160ddd) // `totalSupply()`.
            if iszero(
                and(gt(returndatasize(), 0x1f), staticcall(gas(), token, 0x1c, 0x04, 0x00, 0x20))
            ) {
                mstore(0x00, 0x54cd9435) // `TotalSupplyQueryFailed()`.
                revert(0x1c, 0x04)
            }
            result := mload(0x00)
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// If the initial attempt fails, try to use Permit2 to transfer the token.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for the current contract to manage.
    function safeTransferFrom2(address token, address from, address to, uint256 amount) internal {
        if (!trySafeTransferFrom(token, from, to, amount)) {
            permit2TransferFrom(token, from, to, amount);
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to` via Permit2.
    /// Reverts upon failure.
    function permit2TransferFrom(address token, address from, address to, uint256 amount)
        internal
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(add(m, 0x74), shr(96, shl(96, token)))
            mstore(add(m, 0x54), amount)
            mstore(add(m, 0x34), to)
            mstore(add(m, 0x20), shl(96, from))
            // `transferFrom(address,address,uint160,address)`.
            mstore(m, 0x36c78516000000000000000000000000)
            let p := PERMIT2
            let exists := eq(chainid(), 1)
            if iszero(exists) { exists := iszero(iszero(extcodesize(p))) }
            if iszero(
                and(
                    call(gas(), p, 0, add(m, 0x10), 0x84, codesize(), 0x00),
                    lt(iszero(extcodesize(token)), exists) // Token has code and Permit2 exists.
                )
            ) {
                mstore(0x00, 0x7939f4248757f0fd) // `TransferFromFailed()` or `Permit2AmountOverflow()`.
                revert(add(0x18, shl(2, iszero(iszero(shr(160, amount))))), 0x04)
            }
        }
    }

    /// @dev Permit a user to spend a given amount of
    /// another user's tokens via native EIP-2612 permit if possible, falling
    /// back to Permit2 if native permit fails or is not implemented on the token.
    function permit2(
        address token,
        address owner,
        address spender,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        bool success;
        /// @solidity memory-safe-assembly
        assembly {
            for {} shl(96, xor(token, WETH9)) {} {
                mstore(0x00, 0x3644e515) // `DOMAIN_SEPARATOR()`.
                if iszero(
                    and( // The arguments of `and` are evaluated from right to left.
                        lt(iszero(mload(0x00)), eq(returndatasize(), 0x20)), // Returns 1 non-zero word.
                        // Gas stipend to limit gas burn for tokens that don't refund gas when
                        // an non-existing function is called. 5K should be enough for a SLOAD.
                        staticcall(5000, token, 0x1c, 0x04, 0x00, 0x20)
                    )
                ) { break }
                // After here, we can be sure that token is a contract.
                let m := mload(0x40)
                mstore(add(m, 0x34), spender)
                mstore(add(m, 0x20), shl(96, owner))
                mstore(add(m, 0x74), deadline)
                if eq(mload(0x00), DAI_DOMAIN_SEPARATOR) {
                    mstore(0x14, owner)
                    mstore(0x00, 0x7ecebe00000000000000000000000000) // `nonces(address)`.
                    mstore(
                        add(m, 0x94),
                        lt(iszero(amount), staticcall(gas(), token, 0x10, 0x24, add(m, 0x54), 0x20))
                    )
                    mstore(m, 0x8fcbaf0c000000000000000000000000) // `IDAIPermit.permit`.
                    // `nonces` is already at `add(m, 0x54)`.
                    // `amount != 0` is already stored at `add(m, 0x94)`.
                    mstore(add(m, 0xb4), and(0xff, v))
                    mstore(add(m, 0xd4), r)
                    mstore(add(m, 0xf4), s)
                    success := call(gas(), token, 0, add(m, 0x10), 0x104, codesize(), 0x00)
                    break
                }
                mstore(m, 0xd505accf000000000000000000000000) // `IERC20Permit.permit`.
                mstore(add(m, 0x54), amount)
                mstore(add(m, 0x94), and(0xff, v))
                mstore(add(m, 0xb4), r)
                mstore(add(m, 0xd4), s)
                success := call(gas(), token, 0, add(m, 0x10), 0xe4, codesize(), 0x00)
                break
            }
        }
        if (!success) simplePermit2(token, owner, spender, amount, deadline, v, r, s);
    }

    /// @dev Simple permit on the Permit2 contract.
    function simplePermit2(
        address token,
        address owner,
        address spender,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, 0x927da105) // `allowance(address,address,address)`.
            {
                let addressMask := shr(96, not(0))
                mstore(add(m, 0x20), and(addressMask, owner))
                mstore(add(m, 0x40), and(addressMask, token))
                mstore(add(m, 0x60), and(addressMask, spender))
                mstore(add(m, 0xc0), and(addressMask, spender))
            }
            let p := mul(PERMIT2, iszero(shr(160, amount)))
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x5f), // Returns 3 words: `amount`, `expiration`, `nonce`.
                    staticcall(gas(), p, add(m, 0x1c), 0x64, add(m, 0x60), 0x60)
                )
            ) {
                mstore(0x00, 0x6b836e6b8757f0fd) // `Permit2Failed()` or `Permit2AmountOverflow()`.
                revert(add(0x18, shl(2, iszero(p))), 0x04)
            }
            mstore(m, 0x2b67b570) // `Permit2.permit` (PermitSingle variant).
            // `owner` is already `add(m, 0x20)`.
            // `token` is already at `add(m, 0x40)`.
            mstore(add(m, 0x60), amount)
            mstore(add(m, 0x80), 0xffffffffffff) // `expiration = type(uint48).max`.
            // `nonce` is already at `add(m, 0xa0)`.
            // `spender` is already at `add(m, 0xc0)`.
            mstore(add(m, 0xe0), deadline)
            mstore(add(m, 0x100), 0x100) // `signature` offset.
            mstore(add(m, 0x120), 0x41) // `signature` length.
            mstore(add(m, 0x140), r)
            mstore(add(m, 0x160), s)
            mstore(add(m, 0x180), shl(248, v))
            if iszero( // Revert if token does not have code, or if the call fails.
            mul(extcodesize(token), call(gas(), p, 0, add(m, 0x1c), 0x184, codesize(), 0x00))) {
                mstore(0x00, 0x6b836e6b) // `Permit2Failed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Approves `spender` to spend `amount` of `token` for `address(this)`.
    function permit2Approve(address token, address spender, uint160 amount, uint48 expiration)
        internal
    {
        /// @solidity memory-safe-assembly
        assembly {
            let addressMask := shr(96, not(0))
            let m := mload(0x40)
            mstore(m, 0x87517c45) // `approve(address,address,uint160,uint48)`.
            mstore(add(m, 0x20), and(addressMask, token))
            mstore(add(m, 0x40), and(addressMask, spender))
            mstore(add(m, 0x60), and(addressMask, amount))
            mstore(add(m, 0x80), and(0xffffffffffff, expiration))
            if iszero(call(gas(), PERMIT2, 0, add(m, 0x1c), 0xa0, codesize(), 0x00)) {
                mstore(0x00, 0x324f14ae) // `Permit2ApproveFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Revokes an approval for `token` and `spender` for `address(this)`.
    function permit2Lockdown(address token, address spender) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, 0xcc53287f) // `Permit2.lockdown`.
            mstore(add(m, 0x20), 0x20) // Offset of the `approvals`.
            mstore(add(m, 0x40), 1) // `approvals.length`.
            mstore(add(m, 0x60), shr(96, shl(96, token)))
            mstore(add(m, 0x80), shr(96, shl(96, spender)))
            if iszero(call(gas(), PERMIT2, 0, add(m, 0x1c), 0xa0, codesize(), 0x00)) {
                mstore(0x00, 0x96b3de23) // `Permit2LockdownFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }
}

File 3 of 6 : SafeCastLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Safe integer casting library that reverts on overflow.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeCastLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol)
/// @dev Optimized for runtime gas for very high number of optimizer runs (i.e. >= 1000000).
library SafeCastLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Unable to cast to the target type due to overflow.
    error Overflow();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*          UNSIGNED INTEGER SAFE CASTING OPERATIONS          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Casts `x` to a uint8. Reverts on overflow.
    function toUint8(uint256 x) internal pure returns (uint8) {
        if (x >= 1 << 8) _revertOverflow();
        return uint8(x);
    }

    /// @dev Casts `x` to a uint16. Reverts on overflow.
    function toUint16(uint256 x) internal pure returns (uint16) {
        if (x >= 1 << 16) _revertOverflow();
        return uint16(x);
    }

    /// @dev Casts `x` to a uint24. Reverts on overflow.
    function toUint24(uint256 x) internal pure returns (uint24) {
        if (x >= 1 << 24) _revertOverflow();
        return uint24(x);
    }

    /// @dev Casts `x` to a uint32. Reverts on overflow.
    function toUint32(uint256 x) internal pure returns (uint32) {
        if (x >= 1 << 32) _revertOverflow();
        return uint32(x);
    }

    /// @dev Casts `x` to a uint40. Reverts on overflow.
    function toUint40(uint256 x) internal pure returns (uint40) {
        if (x >= 1 << 40) _revertOverflow();
        return uint40(x);
    }

    /// @dev Casts `x` to a uint48. Reverts on overflow.
    function toUint48(uint256 x) internal pure returns (uint48) {
        if (x >= 1 << 48) _revertOverflow();
        return uint48(x);
    }

    /// @dev Casts `x` to a uint56. Reverts on overflow.
    function toUint56(uint256 x) internal pure returns (uint56) {
        if (x >= 1 << 56) _revertOverflow();
        return uint56(x);
    }

    /// @dev Casts `x` to a uint64. Reverts on overflow.
    function toUint64(uint256 x) internal pure returns (uint64) {
        if (x >= 1 << 64) _revertOverflow();
        return uint64(x);
    }

    /// @dev Casts `x` to a uint72. Reverts on overflow.
    function toUint72(uint256 x) internal pure returns (uint72) {
        if (x >= 1 << 72) _revertOverflow();
        return uint72(x);
    }

    /// @dev Casts `x` to a uint80. Reverts on overflow.
    function toUint80(uint256 x) internal pure returns (uint80) {
        if (x >= 1 << 80) _revertOverflow();
        return uint80(x);
    }

    /// @dev Casts `x` to a uint88. Reverts on overflow.
    function toUint88(uint256 x) internal pure returns (uint88) {
        if (x >= 1 << 88) _revertOverflow();
        return uint88(x);
    }

    /// @dev Casts `x` to a uint96. Reverts on overflow.
    function toUint96(uint256 x) internal pure returns (uint96) {
        if (x >= 1 << 96) _revertOverflow();
        return uint96(x);
    }

    /// @dev Casts `x` to a uint104. Reverts on overflow.
    function toUint104(uint256 x) internal pure returns (uint104) {
        if (x >= 1 << 104) _revertOverflow();
        return uint104(x);
    }

    /// @dev Casts `x` to a uint112. Reverts on overflow.
    function toUint112(uint256 x) internal pure returns (uint112) {
        if (x >= 1 << 112) _revertOverflow();
        return uint112(x);
    }

    /// @dev Casts `x` to a uint120. Reverts on overflow.
    function toUint120(uint256 x) internal pure returns (uint120) {
        if (x >= 1 << 120) _revertOverflow();
        return uint120(x);
    }

    /// @dev Casts `x` to a uint128. Reverts on overflow.
    function toUint128(uint256 x) internal pure returns (uint128) {
        if (x >= 1 << 128) _revertOverflow();
        return uint128(x);
    }

    /// @dev Casts `x` to a uint136. Reverts on overflow.
    function toUint136(uint256 x) internal pure returns (uint136) {
        if (x >= 1 << 136) _revertOverflow();
        return uint136(x);
    }

    /// @dev Casts `x` to a uint144. Reverts on overflow.
    function toUint144(uint256 x) internal pure returns (uint144) {
        if (x >= 1 << 144) _revertOverflow();
        return uint144(x);
    }

    /// @dev Casts `x` to a uint152. Reverts on overflow.
    function toUint152(uint256 x) internal pure returns (uint152) {
        if (x >= 1 << 152) _revertOverflow();
        return uint152(x);
    }

    /// @dev Casts `x` to a uint160. Reverts on overflow.
    function toUint160(uint256 x) internal pure returns (uint160) {
        if (x >= 1 << 160) _revertOverflow();
        return uint160(x);
    }

    /// @dev Casts `x` to a uint168. Reverts on overflow.
    function toUint168(uint256 x) internal pure returns (uint168) {
        if (x >= 1 << 168) _revertOverflow();
        return uint168(x);
    }

    /// @dev Casts `x` to a uint176. Reverts on overflow.
    function toUint176(uint256 x) internal pure returns (uint176) {
        if (x >= 1 << 176) _revertOverflow();
        return uint176(x);
    }

    /// @dev Casts `x` to a uint184. Reverts on overflow.
    function toUint184(uint256 x) internal pure returns (uint184) {
        if (x >= 1 << 184) _revertOverflow();
        return uint184(x);
    }

    /// @dev Casts `x` to a uint192. Reverts on overflow.
    function toUint192(uint256 x) internal pure returns (uint192) {
        if (x >= 1 << 192) _revertOverflow();
        return uint192(x);
    }

    /// @dev Casts `x` to a uint200. Reverts on overflow.
    function toUint200(uint256 x) internal pure returns (uint200) {
        if (x >= 1 << 200) _revertOverflow();
        return uint200(x);
    }

    /// @dev Casts `x` to a uint208. Reverts on overflow.
    function toUint208(uint256 x) internal pure returns (uint208) {
        if (x >= 1 << 208) _revertOverflow();
        return uint208(x);
    }

    /// @dev Casts `x` to a uint216. Reverts on overflow.
    function toUint216(uint256 x) internal pure returns (uint216) {
        if (x >= 1 << 216) _revertOverflow();
        return uint216(x);
    }

    /// @dev Casts `x` to a uint224. Reverts on overflow.
    function toUint224(uint256 x) internal pure returns (uint224) {
        if (x >= 1 << 224) _revertOverflow();
        return uint224(x);
    }

    /// @dev Casts `x` to a uint232. Reverts on overflow.
    function toUint232(uint256 x) internal pure returns (uint232) {
        if (x >= 1 << 232) _revertOverflow();
        return uint232(x);
    }

    /// @dev Casts `x` to a uint240. Reverts on overflow.
    function toUint240(uint256 x) internal pure returns (uint240) {
        if (x >= 1 << 240) _revertOverflow();
        return uint240(x);
    }

    /// @dev Casts `x` to a uint248. Reverts on overflow.
    function toUint248(uint256 x) internal pure returns (uint248) {
        if (x >= 1 << 248) _revertOverflow();
        return uint248(x);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*           SIGNED INTEGER SAFE CASTING OPERATIONS           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Casts `x` to a int8. Reverts on overflow.
    function toInt8(int256 x) internal pure returns (int8) {
        unchecked {
            if (((1 << 7) + uint256(x)) >> 8 == uint256(0)) return int8(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int16. Reverts on overflow.
    function toInt16(int256 x) internal pure returns (int16) {
        unchecked {
            if (((1 << 15) + uint256(x)) >> 16 == uint256(0)) return int16(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int24. Reverts on overflow.
    function toInt24(int256 x) internal pure returns (int24) {
        unchecked {
            if (((1 << 23) + uint256(x)) >> 24 == uint256(0)) return int24(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int32. Reverts on overflow.
    function toInt32(int256 x) internal pure returns (int32) {
        unchecked {
            if (((1 << 31) + uint256(x)) >> 32 == uint256(0)) return int32(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int40. Reverts on overflow.
    function toInt40(int256 x) internal pure returns (int40) {
        unchecked {
            if (((1 << 39) + uint256(x)) >> 40 == uint256(0)) return int40(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int48. Reverts on overflow.
    function toInt48(int256 x) internal pure returns (int48) {
        unchecked {
            if (((1 << 47) + uint256(x)) >> 48 == uint256(0)) return int48(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int56. Reverts on overflow.
    function toInt56(int256 x) internal pure returns (int56) {
        unchecked {
            if (((1 << 55) + uint256(x)) >> 56 == uint256(0)) return int56(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int64. Reverts on overflow.
    function toInt64(int256 x) internal pure returns (int64) {
        unchecked {
            if (((1 << 63) + uint256(x)) >> 64 == uint256(0)) return int64(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int72. Reverts on overflow.
    function toInt72(int256 x) internal pure returns (int72) {
        unchecked {
            if (((1 << 71) + uint256(x)) >> 72 == uint256(0)) return int72(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int80. Reverts on overflow.
    function toInt80(int256 x) internal pure returns (int80) {
        unchecked {
            if (((1 << 79) + uint256(x)) >> 80 == uint256(0)) return int80(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int88. Reverts on overflow.
    function toInt88(int256 x) internal pure returns (int88) {
        unchecked {
            if (((1 << 87) + uint256(x)) >> 88 == uint256(0)) return int88(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int96. Reverts on overflow.
    function toInt96(int256 x) internal pure returns (int96) {
        unchecked {
            if (((1 << 95) + uint256(x)) >> 96 == uint256(0)) return int96(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int104. Reverts on overflow.
    function toInt104(int256 x) internal pure returns (int104) {
        unchecked {
            if (((1 << 103) + uint256(x)) >> 104 == uint256(0)) return int104(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int112. Reverts on overflow.
    function toInt112(int256 x) internal pure returns (int112) {
        unchecked {
            if (((1 << 111) + uint256(x)) >> 112 == uint256(0)) return int112(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int120. Reverts on overflow.
    function toInt120(int256 x) internal pure returns (int120) {
        unchecked {
            if (((1 << 119) + uint256(x)) >> 120 == uint256(0)) return int120(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int128. Reverts on overflow.
    function toInt128(int256 x) internal pure returns (int128) {
        unchecked {
            if (((1 << 127) + uint256(x)) >> 128 == uint256(0)) return int128(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int136. Reverts on overflow.
    function toInt136(int256 x) internal pure returns (int136) {
        unchecked {
            if (((1 << 135) + uint256(x)) >> 136 == uint256(0)) return int136(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int144. Reverts on overflow.
    function toInt144(int256 x) internal pure returns (int144) {
        unchecked {
            if (((1 << 143) + uint256(x)) >> 144 == uint256(0)) return int144(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int152. Reverts on overflow.
    function toInt152(int256 x) internal pure returns (int152) {
        unchecked {
            if (((1 << 151) + uint256(x)) >> 152 == uint256(0)) return int152(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int160. Reverts on overflow.
    function toInt160(int256 x) internal pure returns (int160) {
        unchecked {
            if (((1 << 159) + uint256(x)) >> 160 == uint256(0)) return int160(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int168. Reverts on overflow.
    function toInt168(int256 x) internal pure returns (int168) {
        unchecked {
            if (((1 << 167) + uint256(x)) >> 168 == uint256(0)) return int168(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int176. Reverts on overflow.
    function toInt176(int256 x) internal pure returns (int176) {
        unchecked {
            if (((1 << 175) + uint256(x)) >> 176 == uint256(0)) return int176(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int184. Reverts on overflow.
    function toInt184(int256 x) internal pure returns (int184) {
        unchecked {
            if (((1 << 183) + uint256(x)) >> 184 == uint256(0)) return int184(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int192. Reverts on overflow.
    function toInt192(int256 x) internal pure returns (int192) {
        unchecked {
            if (((1 << 191) + uint256(x)) >> 192 == uint256(0)) return int192(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int200. Reverts on overflow.
    function toInt200(int256 x) internal pure returns (int200) {
        unchecked {
            if (((1 << 199) + uint256(x)) >> 200 == uint256(0)) return int200(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int208. Reverts on overflow.
    function toInt208(int256 x) internal pure returns (int208) {
        unchecked {
            if (((1 << 207) + uint256(x)) >> 208 == uint256(0)) return int208(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int216. Reverts on overflow.
    function toInt216(int256 x) internal pure returns (int216) {
        unchecked {
            if (((1 << 215) + uint256(x)) >> 216 == uint256(0)) return int216(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int224. Reverts on overflow.
    function toInt224(int256 x) internal pure returns (int224) {
        unchecked {
            if (((1 << 223) + uint256(x)) >> 224 == uint256(0)) return int224(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int232. Reverts on overflow.
    function toInt232(int256 x) internal pure returns (int232) {
        unchecked {
            if (((1 << 231) + uint256(x)) >> 232 == uint256(0)) return int232(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int240. Reverts on overflow.
    function toInt240(int256 x) internal pure returns (int240) {
        unchecked {
            if (((1 << 239) + uint256(x)) >> 240 == uint256(0)) return int240(x);
            _revertOverflow();
        }
    }

    /// @dev Casts `x` to a int248. Reverts on overflow.
    function toInt248(int256 x) internal pure returns (int248) {
        unchecked {
            if (((1 << 247) + uint256(x)) >> 248 == uint256(0)) return int248(x);
            _revertOverflow();
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               OTHER SAFE CASTING OPERATIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Casts `x` to a int8. Reverts on overflow.
    function toInt8(uint256 x) internal pure returns (int8) {
        if (x >= 1 << 7) _revertOverflow();
        return int8(int256(x));
    }

    /// @dev Casts `x` to a int16. Reverts on overflow.
    function toInt16(uint256 x) internal pure returns (int16) {
        if (x >= 1 << 15) _revertOverflow();
        return int16(int256(x));
    }

    /// @dev Casts `x` to a int24. Reverts on overflow.
    function toInt24(uint256 x) internal pure returns (int24) {
        if (x >= 1 << 23) _revertOverflow();
        return int24(int256(x));
    }

    /// @dev Casts `x` to a int32. Reverts on overflow.
    function toInt32(uint256 x) internal pure returns (int32) {
        if (x >= 1 << 31) _revertOverflow();
        return int32(int256(x));
    }

    /// @dev Casts `x` to a int40. Reverts on overflow.
    function toInt40(uint256 x) internal pure returns (int40) {
        if (x >= 1 << 39) _revertOverflow();
        return int40(int256(x));
    }

    /// @dev Casts `x` to a int48. Reverts on overflow.
    function toInt48(uint256 x) internal pure returns (int48) {
        if (x >= 1 << 47) _revertOverflow();
        return int48(int256(x));
    }

    /// @dev Casts `x` to a int56. Reverts on overflow.
    function toInt56(uint256 x) internal pure returns (int56) {
        if (x >= 1 << 55) _revertOverflow();
        return int56(int256(x));
    }

    /// @dev Casts `x` to a int64. Reverts on overflow.
    function toInt64(uint256 x) internal pure returns (int64) {
        if (x >= 1 << 63) _revertOverflow();
        return int64(int256(x));
    }

    /// @dev Casts `x` to a int72. Reverts on overflow.
    function toInt72(uint256 x) internal pure returns (int72) {
        if (x >= 1 << 71) _revertOverflow();
        return int72(int256(x));
    }

    /// @dev Casts `x` to a int80. Reverts on overflow.
    function toInt80(uint256 x) internal pure returns (int80) {
        if (x >= 1 << 79) _revertOverflow();
        return int80(int256(x));
    }

    /// @dev Casts `x` to a int88. Reverts on overflow.
    function toInt88(uint256 x) internal pure returns (int88) {
        if (x >= 1 << 87) _revertOverflow();
        return int88(int256(x));
    }

    /// @dev Casts `x` to a int96. Reverts on overflow.
    function toInt96(uint256 x) internal pure returns (int96) {
        if (x >= 1 << 95) _revertOverflow();
        return int96(int256(x));
    }

    /// @dev Casts `x` to a int104. Reverts on overflow.
    function toInt104(uint256 x) internal pure returns (int104) {
        if (x >= 1 << 103) _revertOverflow();
        return int104(int256(x));
    }

    /// @dev Casts `x` to a int112. Reverts on overflow.
    function toInt112(uint256 x) internal pure returns (int112) {
        if (x >= 1 << 111) _revertOverflow();
        return int112(int256(x));
    }

    /// @dev Casts `x` to a int120. Reverts on overflow.
    function toInt120(uint256 x) internal pure returns (int120) {
        if (x >= 1 << 119) _revertOverflow();
        return int120(int256(x));
    }

    /// @dev Casts `x` to a int128. Reverts on overflow.
    function toInt128(uint256 x) internal pure returns (int128) {
        if (x >= 1 << 127) _revertOverflow();
        return int128(int256(x));
    }

    /// @dev Casts `x` to a int136. Reverts on overflow.
    function toInt136(uint256 x) internal pure returns (int136) {
        if (x >= 1 << 135) _revertOverflow();
        return int136(int256(x));
    }

    /// @dev Casts `x` to a int144. Reverts on overflow.
    function toInt144(uint256 x) internal pure returns (int144) {
        if (x >= 1 << 143) _revertOverflow();
        return int144(int256(x));
    }

    /// @dev Casts `x` to a int152. Reverts on overflow.
    function toInt152(uint256 x) internal pure returns (int152) {
        if (x >= 1 << 151) _revertOverflow();
        return int152(int256(x));
    }

    /// @dev Casts `x` to a int160. Reverts on overflow.
    function toInt160(uint256 x) internal pure returns (int160) {
        if (x >= 1 << 159) _revertOverflow();
        return int160(int256(x));
    }

    /// @dev Casts `x` to a int168. Reverts on overflow.
    function toInt168(uint256 x) internal pure returns (int168) {
        if (x >= 1 << 167) _revertOverflow();
        return int168(int256(x));
    }

    /// @dev Casts `x` to a int176. Reverts on overflow.
    function toInt176(uint256 x) internal pure returns (int176) {
        if (x >= 1 << 175) _revertOverflow();
        return int176(int256(x));
    }

    /// @dev Casts `x` to a int184. Reverts on overflow.
    function toInt184(uint256 x) internal pure returns (int184) {
        if (x >= 1 << 183) _revertOverflow();
        return int184(int256(x));
    }

    /// @dev Casts `x` to a int192. Reverts on overflow.
    function toInt192(uint256 x) internal pure returns (int192) {
        if (x >= 1 << 191) _revertOverflow();
        return int192(int256(x));
    }

    /// @dev Casts `x` to a int200. Reverts on overflow.
    function toInt200(uint256 x) internal pure returns (int200) {
        if (x >= 1 << 199) _revertOverflow();
        return int200(int256(x));
    }

    /// @dev Casts `x` to a int208. Reverts on overflow.
    function toInt208(uint256 x) internal pure returns (int208) {
        if (x >= 1 << 207) _revertOverflow();
        return int208(int256(x));
    }

    /// @dev Casts `x` to a int216. Reverts on overflow.
    function toInt216(uint256 x) internal pure returns (int216) {
        if (x >= 1 << 215) _revertOverflow();
        return int216(int256(x));
    }

    /// @dev Casts `x` to a int224. Reverts on overflow.
    function toInt224(uint256 x) internal pure returns (int224) {
        if (x >= 1 << 223) _revertOverflow();
        return int224(int256(x));
    }

    /// @dev Casts `x` to a int232. Reverts on overflow.
    function toInt232(uint256 x) internal pure returns (int232) {
        if (x >= 1 << 231) _revertOverflow();
        return int232(int256(x));
    }

    /// @dev Casts `x` to a int240. Reverts on overflow.
    function toInt240(uint256 x) internal pure returns (int240) {
        if (x >= 1 << 239) _revertOverflow();
        return int240(int256(x));
    }

    /// @dev Casts `x` to a int248. Reverts on overflow.
    function toInt248(uint256 x) internal pure returns (int248) {
        if (x >= 1 << 247) _revertOverflow();
        return int248(int256(x));
    }

    /// @dev Casts `x` to a int256. Reverts on overflow.
    function toInt256(uint256 x) internal pure returns (int256) {
        if (int256(x) >= 0) return int256(x);
        _revertOverflow();
    }

    /// @dev Casts `x` to a uint256. Reverts on overflow.
    function toUint256(int256 x) internal pure returns (uint256) {
        if (x >= 0) return uint256(x);
        _revertOverflow();
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function _revertOverflow() private pure {
        /// @solidity memory-safe-assembly
        assembly {
            // Store the function selector of `Overflow()`.
            mstore(0x00, 0x35278d12)
            // Revert with (offset, size).
            revert(0x1c, 0x04)
        }
    }
}

//SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.28 <0.9.0;

struct ValidatorView {
    address authAddress;
    uint64 flags;
    uint256 executionStake;
    uint256 executionAccumulator;
    uint256 executionCommission;
    uint256 executionUnclaimedRewards;
    uint256 consensusStake;
    uint256 consensusCommission;
    uint256 snapshotStake;
    uint256 snapshotCommission;
    bytes secpPubkey;
    bytes blsPubkey;
}

struct DelInfo {
    uint256 stake;
    uint256 lastAccumulator;
    uint256 rewards;
    uint256 deltaStake;
    uint256 nextDeltaStake;
    uint64 deltaEpoch;
    uint64 nextDeltaEpoch;
}

struct WithdrawalRequest {
    uint256 amount;
    uint256 accumulator;
    uint64 epoch;
}

interface IMonadStaking {
    function addValidator(
        bytes calldata payload,
        bytes calldata signedSecpMessage,
        bytes calldata signedBlsMessage
    )
        external
        payable
        returns (uint64 validatorId);

    function delegate(uint64 validatorId) external payable returns (bool success);

    function undelegate(uint64 validatorId, uint256 amount, uint8 withdrawId) external returns (bool success);

    function compound(uint64 validatorId) external returns (bool success);

    function withdraw(uint64 validatorId, uint8 withdrawId) external returns (bool success);

    function claimRewards(uint64 validatorId) external returns (bool success);

    function changeCommission(uint64 validatorId, uint256 commission) external returns (bool success);

    function externalReward(uint64 validatorId) external payable returns (bool success);

    function getValidator(uint64 validatorId)
        external
        returns (
            address authAddress,
            uint64 flags,
            uint256 stake,
            uint256 accRewardPerToken,
            uint256 commission,
            uint256 unclaimedRewards,
            uint256 consensusStake,
            uint256 consensusCommission,
            uint256 snapshotStake,
            uint256 snapshotCommission,
            bytes memory secpPubkey,
            bytes memory blsPubkey
        );

    function getDelegator(
        uint64 validatorId,
        address delegator
    )
        external
        returns (
            uint256 stake,
            uint256 accRewardPerToken,
            uint256 unclaimedRewards,
            uint256 deltaStake,
            uint256 nextDeltaStake,
            uint64 deltaEpoch,
            uint64 nextDeltaEpoch
        );

    function getWithdrawalRequest(
        uint64 validatorId,
        address delegator,
        uint8 withdrawId
    )
        external
        returns (uint256 withdrawalAmount, uint256 accRewardPerToken, uint64 withdrawEpoch);

    function getConsensusValidatorSet(uint32 startIndex)
        external
        returns (bool isDone, uint32 nextIndex, uint64[] memory valIds);

    function getSnapshotValidatorSet(uint32 startIndex)
        external
        returns (bool isDone, uint32 nextIndex, uint64[] memory valIds);

    function getExecutionValidatorSet(uint32 startIndex)
        external
        returns (bool isDone, uint32 nextIndex, uint64[] memory valIds);

    function getDelegations(
        address delegator,
        uint64 startValId
    )
        external
        returns (bool isDone, uint64 nextValId, uint64[] memory valIds);

    function getDelegators(
        uint64 validatorId,
        address startDelegator
    )
        external
        returns (bool isDone, address nextDelegator, address[] memory delegators);

    function getEpoch() external returns (uint64 epoch, bool inEpochDelayPeriod);

    /// @notice Returns the validator ID of the current block proposer/author for this block
    /// @dev Temporary method name used by ShMonad to avoid relying on block.coinbase; mocked in tests
    function getProposerValId() external returns (uint64 val_id);

    function syscallOnEpochChange(uint64 epoch) external;

    function syscallReward(address blockAuthor) external;

    function syscallSnapshot() external;

    // ================================ //
    //             Constants            //
    // ================================ //
    // NOTE: The precompile has these constants internally but does NOT expose them as view functions.
    // Production code uses DUST_THRESHOLD and WITHDRAWAL_DELAY from Constants.sol.
    // Test code uses all constants from MockMonadStakingPrecompile.sol:
    // - MON = 1e18
    // - MIN_VALIDATE_STAKE = 100_000 * 1e18
    // - ACTIVE_VALIDATOR_STAKE = 25_000_000 * 1e18
    // - UNIT_BIAS = 1e36
    // - DUST_THRESHOLD = 1e9 (used in production)
    // - MAX_EXTERNAL_REWARD = 1e25
    // - WITHDRAWAL_DELAY = 1 (used in production)
    // - PAGINATED_RESULTS_SIZE = 100

    event ValidatorCreated(uint64 indexed validatorId, address indexed authAddress);
    event ValidatorStatusChanged(uint64 indexed validatorId, address indexed authAddress, uint64 flags);
    event Delegate(uint64 indexed validatorId, address indexed delegator, uint256 amount, uint64 activationEpoch);
    event Undelegate(
        uint64 indexed validatorId, address indexed delegator, uint8 withdrawId, uint256 amount, uint64 activationEpoch
    );
    event Withdraw(
        uint64 indexed validatorId, address indexed delegator, uint8 withdrawId, uint256 amount, uint64 withdrawEpoch
    );
    event ClaimRewards(uint256 indexed validatorId, address indexed delegator, uint256 amount);
    event CommissionChanged(uint256 indexed validatorId, uint256 oldCommission, uint256 newCommission);
}

//SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.28 <0.9.0;

interface ICoinbase {
    // ================================ //
    //            Constants             //
    // ================================ //
    // Public immutables surfaced via autogenerated getters
    function VAL_ID() external view returns (uint64);
    function SHMONAD() external view returns (address);
    function AUTH_ADDRESS() external view returns (address);

    // ================================ //
    //          Core Function           //
    // ================================ //
    function process() external returns (bool success);

    // ================================ //
    //         onlyAuth Setters         //
    // ================================ //
    function updateCommissionRate(uint256 newCommissionRate) external;
    function updateCommissionRateFromStakingConfig() external;
    function updateCommissionRecipient(address newRecipient) external;

    // ================================ //
    //               Views              //
    // ================================ //
    function getCommissionRate() external view returns (uint256);
    function getCommissionRecipient() external view returns (address);
}

File 6 of 6 : Constants.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.28 <0.9.0;

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

IMonadStaking constant STAKING = IMonadStaking(0x0000000000000000000000000000000000001000);

// NOTE: These constants exist internally in the precompile but are NOT exposed as view functions.
// Only constants used in production code are defined here. Test-only constants remain in MockMonadStakingPrecompile.
uint256 constant DUST_THRESHOLD = 1e9; // Minimum stake amount (1 gwei)
uint256 constant WITHDRAWAL_DELAY = 1; // Epochs

address constant NATIVE_TOKEN = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
address constant OWNER_COMMISSION_ACCOUNT = address(0x1111111111111111111111111111111111111111);

// Deterministic deployment salt namespace for Coinbase contracts
uint256 constant COINBASE_PROCESS_GAS_LIMIT = 100_000;
bytes32 constant COINBASE_SALT = keccak256("SHMONAD_COINBASE");
uint256 constant TRANSFER_GAS_LIMIT = 50_000; // gas headroom for multisig recipient support

// Monad staking precompile gas guidance (docs.monad.xyz) + adjustable buffer for mocks/in-flight gas bumps
uint256 constant STAKING_GAS_BUFFER = 10_000;
uint256 constant STAKING_GAS_CLAIM_REWARDS = 155_375;
uint256 constant STAKING_GAS_EXTERNAL_REWARD = 62_300;
uint256 constant STAKING_GAS_DELEGATE = 260_850;
uint256 constant STAKING_GAS_UNDELEGATE = 147_750;
uint256 constant STAKING_GAS_WITHDRAW = 68_675;
uint256 constant STAKING_GAS_GET_WITHDRAWAL_REQUEST = 24_300;
uint256 constant STAKING_GAS_GET_DELEGATOR = 184_900;
uint256 constant STAKING_GAS_GET_VALIDATOR = 97_200;
uint256 constant STAKING_GAS_PROPOSER_VAL_ID = 100;

// EIP-1967 admin slot: bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)
bytes32 constant EIP1967_ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
// NOTE: Top-up period duration is compared against `block.number` in policy logic and is measured in blocks.
// Set to ~1 day on Monad (0.4s blocks): 24*60*60 / 0.4 = 216_000 blocks.
uint32 constant MIN_TOP_UP_PERIOD_BLOCKS = 216_000;
bytes32 constant PERMIT_TYPEHASH =
    keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

uint256 constant ZERO = 0;
uint16 constant BPS_SCALE = 10_000; // Still used for percentage weights/targets outside fee curve math
uint256 constant MIN_VALIDATOR_DEPOSIT = 1e18; // Min amount to do a validator deposit
uint256 constant STAKE_ITERATION_MIN_GAS = 100_000; // Min gas for 1 stake iteration in loop
uint88 constant UNSTAKE_BLOCK_DELAY = 1_209_600; // 7 days if block time is 0.5 seconds
uint256 constant SLASHING_FREEZE_THRESHOLD = 7e16; // 7% of total equity, out of SCALE
uint256 constant ATOMIC_MIN_FEE_WEI = 1e9; // 1 gwei floor for atomic paths

uint256 constant EPOCHS_TRACKED = 8; // Must be a power of 2
uint256 constant MONAD_EPOCH_LENGTH = 50_000; // Measured in blocks
uint256 constant MONAD_EPOCH_DELAY_PERIOD = 5000; // Measured in blocks
uint256 constant MIN_FREE_WITHDRAW_IDS = 8; // Min free withdraw IDs to keep available per validator
uint256 constant SHMONAD_VALIDATOR_DEACTIVATION_PERIOD = 7; // How long it takes to cycle out an inactive validator

uint256 constant SCALE = 1e18; // 100%
uint256 constant TARGET_FLOAT = 2e16; // 2%
uint256 constant FLOAT_REBALANCE_SENSITIVITY = 1e14; // 1bp
uint256 constant FLOAT_PLACEHOLDER = 1;

uint64 constant UNKNOWN_VAL_ID = type(uint64).max - 1;
address constant UNKNOWN_VAL_ADDRESS = address(uint160(type(uint160).max - 1));
// ID-based sentinels for validator crank linked list
uint64 constant FIRST_VAL_ID = 1_111_111_111_111_111_111; // 1.111e18 sentinel (fits in uint64)
uint64 constant LAST_VAL_ID = 9_999_999_999_999_999_999; // 9.999e18 sentinel (fits in uint64)

uint256 constant UINT120_MASK = type(uint120).max;

// feeLib constant
uint256 constant RAY = 1e27;

// Default affine fee curve parameters (Ray precision)
// Fee curve: r(u) = m*u + c with
// - c = 8% / 1600 = 1/20000 = 0.005%
// - m chosen so r(1) = 1% + c  => m = 1%
// Therefore: at u = 0 => 0.005%; at u = 1 => 1.005%
uint128 constant DEFAULT_SLOPE_RATE_RAY = uint128(RAY / 100); // m = 1.00%
uint128 constant DEFAULT_Y_INTERCEPT_RAY = uint128(RAY / 20_000); // c = 0.005%

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@openzeppelin-upgradeable/contracts/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@solady/=lib/solady/src/",
    "forge-std/=lib/forge-std/src/",
    "account-abstraction-v7/=lib/account-abstraction-v7/",
    "account-abstraction-v8/=lib/account-abstraction-v8/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "solady/=lib/solady/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 50
  },
  "metadata": {
    "useLiteralContent": true,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"uint64","name":"valId","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CommissionOrRewardFailed","type":"error"},{"inputs":[],"name":"InvalidCommissionRate","type":"error"},{"inputs":[],"name":"OnlyAuthAddress","type":"error"},{"inputs":[],"name":"OnlySelfCaller","type":"error"},{"inputs":[],"name":"OnlyShMonadCaller","type":"error"},{"inputs":[],"name":"RecipientCannotBeZeroAddress","type":"error"},{"inputs":[{"internalType":"uint64","name":"validatorId","type":"uint64"}],"name":"ValidatorNotFoundInPrecompile","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldCommissionRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCommissionRate","type":"uint256"}],"name":"CommissionRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldRecipient","type":"address"},{"indexed":false,"internalType":"address","name":"newRecipient","type":"address"}],"name":"CommissionRecipientUpdated","type":"event"},{"inputs":[],"name":"AUTH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SELF","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHMONAD","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAL_ID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCommissionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCommissionRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"process","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"commissionRecipient","type":"address"},{"internalType":"uint256","name":"validatorCommission","type":"uint256"},{"internalType":"uint256","name":"rewardPortion","type":"uint256"}],"name":"sendCommissionAndRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCommissionRate","type":"uint256"}],"name":"updateCommissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateCommissionRateFromStakingConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRecipient","type":"address"}],"name":"updateCommissionRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

0x610100806040523461027457602081610cff80380380916100208285610321565b8339810103126102745761003390610344565b60808190523360a0523060e0526040516315b6b1cd60e11b81526001600160401b0390911660048201819052905f9081908181602481836110006201a2c0f15f815f935f9361028b575b506101ee575b5050506001600160a01b0381169283156101dc575060c0526c010000000000000000000000008110156101cf576040805190810192906001600160401b038411818510176101bb5760409384528181526001600160601b03831660209182015260a083901b6001600160a01b03191682175f9081558451908152908101929092527f2c40de6ec45500fc9fc0e3b8f163c1cacefcd0e5744039e3ed1259551fb98e5b92917fd5b010b75d0703745f3c15954fbe4ac8aebb10e4c4aa09de04b1e1e195a67b9d908390a18151905f82526020820152a160405161095190816103ae82396080518181816101870152818161024f0152610309015260a05181818160a80152610112015260c0518181816101c0015281816102cc015281816105300152610647015260e05181818161020e01526106020152f35b634e487b7160e01b5f52604160045260245ffd5b6335278d125f526004601cfd5b6319708e7160e01b5f5260045260245ffd5b60408051630eaf323560e31b815291955091935090816004815f6110005af1908115610280575f91610233575b501561022c57505b905f8080610083565b9050610223565b90506040813d604011610278575b8161024e60409383610321565b810103126102745780610262602092610344565b5001518015158103610274575f61021b565b5f80fd5b3d9150610241565b6040513d5f823e3d90fd5b93509150503d805f843e61029f8184610321565b820191610180818403126102745780516001600160a01b0381168103610274576102cb60208301610344565b5060e0820151916101208101519461014082015160018060401b03811161027457816102f8918401610358565b506101608201516001600160401b038111610274576103179201610358565b509092915f61007d565b601f909101601f19168101906001600160401b038211908210176101bb57604052565b51906001600160401b038216820361027457565b81601f82011215610274578051906001600160401b0382116101bb576040519261038c601f8401601f191660200185610321565b8284526020838301011161027457815f9260208093018386015e830101529056fe6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c8062fa3d501461063157806326bd0c4e146105ed5780633e4eb36c146105ce5780633f3b061a146105155780636f7cbce4146102ba57806379e164ab146101ef5780637c359fe0146101ab5780637f4e7d7b146101685780639b29673414610141578063ae61ebe9146100fd5763c33fb8770361000e57346100f9575f3660031901126100f9577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633036100ea5760206100e0610718565b6040519015158152f35b63688065ed60e01b5f5260045ffd5b5f80fd5b346100f9575f3660031901126100f9576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346100f9575f3660031901126100f9575f546040516001600160a01b039091168152602090f35b346100f9575f3660031901126100f95760206040516001600160401b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346100f9575f3660031901126100f9576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346100f95760603660031901126100f9576102086106cd565b602435907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633036102ab5760019180610298575b50506102736044357f000000000000000000000000000000000000000000000000000000000000000061089d565b81610290575b501561028157005b633c3b699360e01b5f5260045ffd5b905081610279565b5f8093508091389361c350f18180610245565b632388e24d60e21b5f5260045ffd5b346100f9575f3660031901126100f9577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610506576040516315b6b1cd60e11b81527f00000000000000000000000000000000000000000000000000000000000000006001600160401b0316600482018190525f9182908181602481836110006201a2c0f15f815f935f9361046f575b506103d8575b5050506001600160a01b0316156103c6575f547fd5b010b75d0703745f3c15954fbe4ac8aebb10e4c4aa09de04b1e1e195a67b9d90604090846001600160a01b03196103a682610802565b60a01b1660018060a01b038316175f5582519160a01c82526020820152a1005b6319708e7160e01b5f5260045260245ffd5b60408051630eaf323560e31b815291965091935090816004815f6110005af1908115610464575f9161041d575b501561041657505b9183808061035b565b905061040d565b90506040813d60401161045c575b81610438604093836106e3565b810103126100f95760208161044f61045693610827565b5001610890565b85610405565b3d915061042b565b6040513d5f823e3d90fd5b93509150503d805f843e61048381846106e3565b820191610180818403126100f95780516001600160a01b03811681036100f9576104af60208301610827565b5060e082015191610120810151946101408201516001600160401b0381116100f957816104dd91840161083b565b506101608201516001600160401b0381116100f9576104fc920161083b565b5090929187610355565b639bfdc6ff60e01b5f5260045ffd5b346100f95760203660031901126100f95761052e6106cd565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610506576001600160a01b031680156105bf575f80546001600160a01b031981168317909155604080516001600160a01b03909216825260208201929092527f2c40de6ec45500fc9fc0e3b8f163c1cacefcd0e5744039e3ed1259551fb98e5b9190a1005b636c38382960e11b5f5260045ffd5b346100f9575f3660031901126100f95760205f5460a01c604051908152f35b346100f9575f3660031901126100f9576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346100f95760203660031901126100f9576004357f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361050657670de0b6b3a764000081116106be575f547fd5b010b75d0703745f3c15954fbe4ac8aebb10e4c4aa09de04b1e1e195a67b9d91604091906001600160a01b03196103a682610802565b63047f2a9760e51b5f5260045ffd5b600435906001600160a01b03821682036100f957565b90601f801991011681019081106001600160401b0382111761070457604052565b634e487b7160e01b5f52604160045260245ffd5b5f604051604081018181106001600160401b03821117610704576040525f546001600160a01b038116825260a01c6020820181905247908181029082820414821517156107ee57670de0b6b3a76400009004918282039182116107ee57670de0b6b3a764000082106107e657516001600160a01b031691303b156100f957604051926379e164ab60e01b84526004840152602483015260448201525f8160648183305af190816107d1575b506107cb5790565b50600190565b6107de9192505f906106e3565b5f905f6107c3565b505050505f90565b634e487b7160e01b5f52601160045260245ffd5b600160601b81101561081a576001600160601b031690565b6335278d125f526004601cfd5b51906001600160401b03821682036100f957565b81601f820112156100f9578051906001600160401b038211610704576040519261086f601f8401601f1916602001856106e3565b828452602083830101116100f957815f9260208093018386015e8301015290565b519081151582036100f957565b6001600160401b036024602092604051948593849263e4b3303b60e01b845216600483015261100062011a6cf15f91816108df575b506108dc57505f90565b90565b9091506020813d602011610913575b816108fb602093836106e3565b810103126100f95761090c90610890565b905f6108d2565b3d91506108ee56fea26469706673582212205d20ca8657067f4f35639a44f2725d7f5b6b63c601ce6d3f8654f7806f7019d364736f6c634300081e0033000000000000000000000000000000000000000000000000000000000000003e

Deployed Bytecode

0x6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c8062fa3d501461063157806326bd0c4e146105ed5780633e4eb36c146105ce5780633f3b061a146105155780636f7cbce4146102ba57806379e164ab146101ef5780637c359fe0146101ab5780637f4e7d7b146101685780639b29673414610141578063ae61ebe9146100fd5763c33fb8770361000e57346100f9575f3660031901126100f9577f0000000000000000000000001b68626dca36c7fe922fd2d55e4f631d962de19c6001600160a01b031633036100ea5760206100e0610718565b6040519015158152f35b63688065ed60e01b5f5260045ffd5b5f80fd5b346100f9575f3660031901126100f9576040517f0000000000000000000000001b68626dca36c7fe922fd2d55e4f631d962de19c6001600160a01b03168152602090f35b346100f9575f3660031901126100f9575f546040516001600160a01b039091168152602090f35b346100f9575f3660031901126100f95760206040516001600160401b037f000000000000000000000000000000000000000000000000000000000000003e168152f35b346100f9575f3660031901126100f9576040517f0000000000000000000000001fc572111f29adbf548eab959d443e02b5a4dd5b6001600160a01b03168152602090f35b346100f95760603660031901126100f9576102086106cd565b602435907f0000000000000000000000007fbf96c38fad9baf4992497544a7b274310d77986001600160a01b031633036102ab5760019180610298575b50506102736044357f000000000000000000000000000000000000000000000000000000000000003e61089d565b81610290575b501561028157005b633c3b699360e01b5f5260045ffd5b905081610279565b5f8093508091389361c350f18180610245565b632388e24d60e21b5f5260045ffd5b346100f9575f3660031901126100f9577f0000000000000000000000001fc572111f29adbf548eab959d443e02b5a4dd5b6001600160a01b03163303610506576040516315b6b1cd60e11b81527f000000000000000000000000000000000000000000000000000000000000003e6001600160401b0316600482018190525f9182908181602481836110006201a2c0f15f815f935f9361046f575b506103d8575b5050506001600160a01b0316156103c6575f547fd5b010b75d0703745f3c15954fbe4ac8aebb10e4c4aa09de04b1e1e195a67b9d90604090846001600160a01b03196103a682610802565b60a01b1660018060a01b038316175f5582519160a01c82526020820152a1005b6319708e7160e01b5f5260045260245ffd5b60408051630eaf323560e31b815291965091935090816004815f6110005af1908115610464575f9161041d575b501561041657505b9183808061035b565b905061040d565b90506040813d60401161045c575b81610438604093836106e3565b810103126100f95760208161044f61045693610827565b5001610890565b85610405565b3d915061042b565b6040513d5f823e3d90fd5b93509150503d805f843e61048381846106e3565b820191610180818403126100f95780516001600160a01b03811681036100f9576104af60208301610827565b5060e082015191610120810151946101408201516001600160401b0381116100f957816104dd91840161083b565b506101608201516001600160401b0381116100f9576104fc920161083b565b5090929187610355565b639bfdc6ff60e01b5f5260045ffd5b346100f95760203660031901126100f95761052e6106cd565b7f0000000000000000000000001fc572111f29adbf548eab959d443e02b5a4dd5b6001600160a01b03163303610506576001600160a01b031680156105bf575f80546001600160a01b031981168317909155604080516001600160a01b03909216825260208201929092527f2c40de6ec45500fc9fc0e3b8f163c1cacefcd0e5744039e3ed1259551fb98e5b9190a1005b636c38382960e11b5f5260045ffd5b346100f9575f3660031901126100f95760205f5460a01c604051908152f35b346100f9575f3660031901126100f9576040517f0000000000000000000000007fbf96c38fad9baf4992497544a7b274310d77986001600160a01b03168152602090f35b346100f95760203660031901126100f9576004357f0000000000000000000000001fc572111f29adbf548eab959d443e02b5a4dd5b6001600160a01b0316330361050657670de0b6b3a764000081116106be575f547fd5b010b75d0703745f3c15954fbe4ac8aebb10e4c4aa09de04b1e1e195a67b9d91604091906001600160a01b03196103a682610802565b63047f2a9760e51b5f5260045ffd5b600435906001600160a01b03821682036100f957565b90601f801991011681019081106001600160401b0382111761070457604052565b634e487b7160e01b5f52604160045260245ffd5b5f604051604081018181106001600160401b03821117610704576040525f546001600160a01b038116825260a01c6020820181905247908181029082820414821517156107ee57670de0b6b3a76400009004918282039182116107ee57670de0b6b3a764000082106107e657516001600160a01b031691303b156100f957604051926379e164ab60e01b84526004840152602483015260448201525f8160648183305af190816107d1575b506107cb5790565b50600190565b6107de9192505f906106e3565b5f905f6107c3565b505050505f90565b634e487b7160e01b5f52601160045260245ffd5b600160601b81101561081a576001600160601b031690565b6335278d125f526004601cfd5b51906001600160401b03821682036100f957565b81601f820112156100f9578051906001600160401b038211610704576040519261086f601f8401601f1916602001856106e3565b828452602083830101116100f957815f9260208093018386015e8301015290565b519081151582036100f957565b6001600160401b036024602092604051948593849263e4b3303b60e01b845216600483015261100062011a6cf15f91816108df575b506108dc57505f90565b90565b9091506020813d602011610913575b816108fb602093836106e3565b810103126100f95761090c90610890565b905f6108d2565b3d91506108ee56fea26469706673582212205d20ca8657067f4f35639a44f2725d7f5b6b63c601ce6d3f8654f7806f7019d364736f6c634300081e0033

Deployed Bytecode Sourcemap

684:6041:2:-:0;;;;;;;;;-1:-1:-1;684:6041:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;684:6041:2;;;;2113:7;-1:-1:-1;;;;;684:6041:2;2099:10;:21;684:6041;;;2356:873;;:::i;:::-;684:6041;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;684:6041:2;;;;;;832:32;-1:-1:-1;;;;;684:6041:2;;;;;;;;;;;;-1:-1:-1;;684:6041:2;;;;;;;;-1:-1:-1;;;;;684:6041:2;;;;;;;;;;;;;;-1:-1:-1;;684:6041:2;;;;;;;-1:-1:-1;;;;;796:30:2;684:6041;;;;;;;;;;-1:-1:-1;;684:6041:2;;;;;;870:37;-1:-1:-1;;;;;684:6041:2;;;;;;;;;;;;-1:-1:-1;;684:6041:2;;;;;;:::i;:::-;;;;2218:4;-1:-1:-1;;;;;684:6041:2;2204:10;:18;684:6041;;;3553:23;;3549:160;;684:6041;;;3747:35;684:6041;;3760:6;3747:35;:::i;:::-;3859:49;;;684:6041;973:6:3;;;;684:6041:2;973:6:3;;;;684:6041:2;973:6:3;684:6041:2;;973:6:3;3859:49:2;;;;;;3549:160;684:6041;8588:108:1;;;;;;;973:6:3;8588:108:1;3549:160:2;;;;684:6041;;;;;;;;;;;;;;;-1:-1:-1;;684:6041:2;;;;2002:12;-1:-1:-1;;;;;684:6041:2;1988:10;:26;684:6041;;;;-1:-1:-1;;;6032:88:2;;4449:6;-1:-1:-1;;;;;684:6041:2;;6032:88;;684:6041;;;;;;;;;6032:88;684:6041;;182:42:3;1175:6;6032:88:2;684:6041;;;;;6032:88;;;684:6041;6028:601;;;684:6041;-1:-1:-1;;;;;;;;684:6041:2;6646:25;1175:6:3;;684:6041:2;3227:4:3;4600:61:2;;684:6041;;3227:4:3;-1:-1:-1;;;;;;4555:29:2;3227:4:3;4555:29:2;:::i;:::-;3227:4:3;;;684:6041:2;;;;;3227:4:3;;;684:6041:2;3227:4:3;684:6041:2;;3227:4:3;;;684:6041:2;;;3227:4:3;;684:6041:2;4600:61;684:6041;1175:6:3;;;;684:6041:2;1175:6:3;684:6041:2;;6032:88;684:6041;1175:6:3;6028:601:2;684:6041;;;-1:-1:-1;;;5368:18:2;;6477:26;;-1:-1:-1;6477:26:2;;-1:-1:-1;684:6041:2;;;;;182:42:3;5368:18:2;;;;;;;684:6041;5368:18;;;6028:601;-1:-1:-1;6534:74:2;;;;;6028:601;;;;;;6534:74;;;;;5368:18;;;684:6041;5368:18;;684:6041;5368:18;;;;;;684:6041;5368:18;;;:::i;:::-;;;684:6041;;;;;1175:6:3;;1284;1175;;:::i;:::-;;684:6041:2;1284:6:3;:::i;:::-;5368:18:2;;;;;;-1:-1:-1;5368:18:2;;;684:6041;;2392:4:3;684:6041:2;2392:4:3;;;;;6032:88:2;;;;;;;;684:6041;6032:88;;;;;;:::i;:::-;;;1175:6:3;;;;;;;;;;-1:-1:-1;;;;;684:6041:2;;;;;;1175:6:3;684:6041:2;1175:6:3;;;:::i;:::-;;684:6041:2;1175:6:3;;;;;;;;;;;;;-1:-1:-1;;;;;1175:6:3;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1175:6:3;;;;;;;;:::i;:::-;;6032:88:2;;;;;;684:6041;;;;;;;;;;;;;;;-1:-1:-1;;684:6041:2;;;;;;:::i;:::-;2002:12;-1:-1:-1;;;;;684:6041:2;1988:10;:26;684:6041;;-1:-1:-1;;;;;684:6041:2;4774:26;;684:6041;;;;;-1:-1:-1;;;;;;684:6041:2;;;;;;;;;;-1:-1:-1;;;;;684:6041:2;;;;;;;;;;;;4964:55;;684:6041;4964:55;684:6041;;;;;;;;;;;;;;;;-1:-1:-1;;684:6041:2;;;;;;3227:4:3;;;684:6041:2;;;;;;;;;;;;-1:-1:-1;;684:6041:2;;;;;;913:29;-1:-1:-1;;;;;684:6041:2;;;;;;;;;;;;-1:-1:-1;;684:6041:2;;;;;;2002:12;-1:-1:-1;;;;;684:6041:2;1988:10;:26;684:6041;;3227:4:3;4050:26:2;;3227:4:3;;684:6041:2;3227:4:3;4245:60:2;;684:6041;;3227:4:3;-1:-1:-1;;;;;;4201:28:2;3227:4:3;4201:28:2;:::i;3227:4:3:-;;;;684:6041:2;3227:4:3;684:6041:2;;3227:4:3;684:6041:2;;;;-1:-1:-1;;;;;684:6041:2;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;684:6041:2;;;;;;;:::o;:::-;;;;-1:-1:-1;684:6041:2;;;;;-1:-1:-1;684:6041:2;2356:873;2461:8;684:6041;;;;;;;;-1:-1:-1;;;;;684:6041:2;;;;;;;2461:8;684:6041;-1:-1:-1;;;;;684:6041:2;;;;;3227:4:3;684:6041:2;;;;;;2561:21;;684:6041;;;;;;;;;;;;;;3227:4:3;684:6041:2;;;;;;;;;;;3227:4:3;2899:38:2;;2895:56;;2392:4:3;-1:-1:-1;;;;;684:6041:2;;2569:4;3040:96;;;;684:6041;;2392:4:3;;;;3040:96:2;;;;;684:6041;2392:4:3;;;684:6041:2;2392:4:3;;;684:6041:2;2461:8;2569:4;3040:96;2569:4;;;3040:96;;;;;;2356:873;-1:-1:-1;3036:187:2;;;2356:873::o;3036:187::-;3151:14;3161:4;3036:187;2356:873::o;3040:96::-;;;;;2461:8;3040:96;;:::i;:::-;2461:8;3040:96;;;;2895:56;2939:12;;;;2461:8;2939:12;:::o;684:6041::-;;;;2461:8;684:6041;;;;;2461:8;684:6041;3395:138:0;-1:-1:-1;;;3469:12:0;;;3465:35;;-1:-1:-1;;;;;3227:4:3;;3395:138:0:o;3465:35::-;23595:191;;;;;;1175:6:3;;684:6041:2;-1:-1:-1;;;;;684:6041:2;;1175:6:3;;;;:::o;:::-;;;;;;;;;;;;-1:-1:-1;;;;;1175:6:3;;;;684:6041:2;;;;;;;-1:-1:-1;;684:6041:2;1175:6:3;;684:6041:2;;:::i;:::-;1175:6:3;;;;;;;;;;;;-1:-1:-1;1175:6:3;;;;;;;;;;;;;;:::o;1284:::-;;684:6041:2;;;;1284:6:3;;;;:::o;5437:372:2:-;-1:-1:-1;;;;;5539:135:2;684:6041;5437:372;684:6041;;2392:4:3;;;;;;;;5539:135:2;;684:6041;5539:135;;;684:6041;182:42:3;1175:6;5539:135:2;684:6041;;5539:135;;;5437:372;-1:-1:-1;5535:268:2;;5780:12;684:6041;5780:12;:::o;5535:268::-;5723:25;:::o;5539:135::-;;;;684:6041;5539:135;;684:6041;5539:135;;;;;;684:6041;5539:135;;;:::i;:::-;;;1284:6:3;;;;;;;:::i;:::-;5539:135:2;;;;;;;-1:-1:-1;5539:135:2;

Swarm Source

ipfs://5d20ca8657067f4f35639a44f2725d7f5b6b63c601ce6d3f8654f7806f7019d3

 Latest 25 blocks (From a total of 33,628 blocks with 40,300.25 MON in fees)

Block Transaction Gas Used Reward
473218332026-01-08 7:57:5316 days ago176785907382,339,267 (1.17%)
0.238365234005214624 MON
473218262026-01-08 7:57:5016 days ago1767859070104,520,211 (2.26%)
0.478326815504064547 MON
473217682026-01-08 7:57:2716 days ago1767859047103,743,968 (1.87%)
0.38126091200562375 MON
473215862026-01-08 7:56:1416 days ago176785897451,789,669 (0.89%)
0.18254623800314 MON
473215492026-01-08 7:55:5916 days ago1767858959146,981,025 (3.49%)
0.731934550004655303 MON
473212322026-01-08 7:53:5216 days ago176785883272,701,103 (1.35%)
0.275671709349596029 MON
473207582026-01-08 7:50:4216 days ago176785864282,194,946 (1.10%)
0.223644492001926135 MON
473207062026-01-08 7:50:2216 days ago176785862272,805,837 (1.40%)
0.295460935763114608 MON
473205392026-01-08 7:49:1416 days ago176785855451,808,021 (0.90%)
0.184418142003295641 MON
473202902026-01-08 7:47:3516 days ago176785845562,242,612 (1.12%)
0.228399762503299667 MON
473195972026-01-08 7:42:5616 days ago176785817661,219,918 (0.61%)
0.124191636003199322 MON
473195462026-01-08 7:42:3616 days ago1767858156115,855,856 (2.93%)
0.622314567775058404 MON
473187672026-01-08 7:37:2416 days ago176785784483,700,086 (1.85%)
0.424068757637228983 MON
473181432026-01-08 7:33:1316 days ago176785759393,400,887 (1.70%)
0.384690474002334826 MON
473180132026-01-08 7:32:2116 days ago176785754151,789,650 (0.89%)
0.182544300004281156 MON
473179662026-01-08 7:32:0216 days ago176785752272,310,644 (1.16%)
0.235827374884925849 MON
473178442026-01-08 7:31:1416 days ago176785747484,589,588 (2.29%)
0.469537976003995681 MON
473172002026-01-08 7:26:5616 days ago1767857216135,869,194 (2.93%)
0.594966661886566182 MON
473171132026-01-08 7:26:2116 days ago176785718153,252,826 (1.63%)
0.331888252 MON
473162582026-01-08 7:20:3816 days ago176785683872,354,325 (1.18%)
0.240142080140899815 MON
473162512026-01-08 7:20:3516 days ago1767856835135,652,749 (2.83%)
0.579229806775932776 MON
473162042026-01-08 7:20:1616 days ago176785681663,175,833 (1.59%)
0.323840407265495772 MON
473160822026-01-08 7:19:2816 days ago1767856768105,374,232 (2.69%)
0.661797397152240792 MON
473158542026-01-08 7:17:5716 days ago176785667772,699,999 (1.35%)
0.275087040278426014 MON
473157752026-01-08 7:17:2516 days ago176785664572,530,002 (1.27%)
0.258232181678646364 MON
view all blocks produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ 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.