ETH Price: $3,343.20 (-1.62%)

Contract

0x6e220Be8511ACc1db8ACD4e2e66f987CF7529Af6
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Broadcast Ve Bal...214185582024-12-17 0:05:5911 days ago1734393959IN
0x6e220Be8...CF7529Af6
0.01 ETH0.0029877815.45918257
Broadcast Ve Bal...209811822024-10-16 22:43:5972 days ago1729118639IN
0x6e220Be8...CF7529Af6
0.01 ETH0.00183349.4862802
Broadcast Ve Bal...209450502024-10-11 21:26:5977 days ago1728682019IN
0x6e220Be8...CF7529Af6
0.01 ETH0.0025722911.41747063
Broadcast Ve Bal...209450482024-10-11 21:26:2377 days ago1728681983IN
0x6e220Be8...CF7529Af6
0.01 ETH0.0022025811.39647197
Broadcast Ve Bal...209450462024-10-11 21:25:5977 days ago1728681959IN
0x6e220Be8...CF7529Af6
0.01 ETH0.001808549.35824176
Broadcast Ve Bal...209450462024-10-11 21:25:5977 days ago1728681959IN
0x6e220Be8...CF7529Af6
0.01 ETH0.002188739.35824176
Broadcast Ve Bal...205258532024-08-14 9:03:59136 days ago1723626239IN
0x6e220Be8...CF7529Af6
0.01 ETH0.000914374.73112137
Broadcast Ve Bal...204251192024-07-31 7:43:47150 days ago1722411827IN
0x6e220Be8...CF7529Af6
0.01 ETH0.000884214.57531783
Broadcast Ve Bal...204251172024-07-31 7:43:23150 days ago1722411803IN
0x6e220Be8...CF7529Af6
0.01 ETH0.001473954.45683449
Broadcast Ve Bal...203964602024-07-27 7:42:59154 days ago1722066179IN
0x6e220Be8...CF7529Af6
0.01 ETH0.00103471.33598067
Broadcast Ve Bal...203961052024-07-27 6:31:11154 days ago1722061871IN
0x6e220Be8...CF7529Af6
0.01 ETH0.001018121.19829774
Broadcast Ve Bal...203265932024-07-17 13:37:35163 days ago1721223455IN
0x6e220Be8...CF7529Af6
0.01 ETH0.0022003711.38574601
Broadcast Ve Bal...203257192024-07-17 10:41:47163 days ago1721212907IN
0x6e220Be8...CF7529Af6
0.01 ETH0.00148647.69131661
Broadcast Ve Bal...203200852024-07-16 15:51:59164 days ago1721145119IN
0x6e220Be8...CF7529Af6
0.01 ETH0.0024528311.11634824
Broadcast Ve Bal...203200792024-07-16 15:50:47164 days ago1721145047IN
0x6e220Be8...CF7529Af6
0.01 ETH0.0022470111.62638147
Broadcast Ve Bal...203124392024-07-15 14:14:11165 days ago1721052851IN
0x6e220Be8...CF7529Af6
0.01 ETH0.001793199.27821934
Broadcast Ve Bal...202903102024-07-12 12:06:23168 days ago1720785983IN
0x6e220Be8...CF7529Af6
0.01 ETH0.001431473.10559745
Broadcast Ve Bal...202881842024-07-12 4:57:11169 days ago1720760231IN
0x6e220Be8...CF7529Af6
0.01 ETH0.000374431.93748027
Broadcast Ve Bal...202881812024-07-12 4:56:35169 days ago1720760195IN
0x6e220Be8...CF7529Af6
0.01 ETH0.001144312.16162611
Broadcast Ve Bal...202879852024-07-12 4:17:11169 days ago1720757831IN
0x6e220Be8...CF7529Af6
0.01 ETH0.000437322.2627919
Broadcast Ve Bal...202859872024-07-11 21:34:47169 days ago1720733687IN
0x6e220Be8...CF7529Af6
0.01 ETH0.00083134.30155886
Broadcast Ve Bal...202823662024-07-11 9:28:11170 days ago1720690091IN
0x6e220Be8...CF7529Af6
0.01 ETH0.0029990814.64205387
Broadcast Ve Bal...202748282024-07-10 8:13:11171 days ago1720599191IN
0x6e220Be8...CF7529Af6
0.01 ETH0.000974225.04075865
Broadcast Ve Bal...202695062024-07-09 14:23:35171 days ago1720535015IN
0x6e220Be8...CF7529Af6
0.01 ETH0.001658748.5825777
Broadcast Ve Bal...202292162024-07-03 23:17:47177 days ago1720048667IN
0x6e220Be8...CF7529Af6
0.01 ETH0.000852854.41306533
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
214185582024-12-17 0:05:5911 days ago1734393959
0x6e220Be8...CF7529Af6
0.00985424 ETH
214185582024-12-17 0:05:5911 days ago1734393959
0x6e220Be8...CF7529Af6
0.00014575 ETH
209811822024-10-16 22:43:5972 days ago1729118639
0x6e220Be8...CF7529Af6
0.00989157 ETH
209811822024-10-16 22:43:5972 days ago1729118639
0x6e220Be8...CF7529Af6
0.00010842 ETH
209450502024-10-11 21:26:5977 days ago1728682019
0x6e220Be8...CF7529Af6
0.01 ETH
209450482024-10-11 21:26:2377 days ago1728681983
0x6e220Be8...CF7529Af6
0.00988543 ETH
209450482024-10-11 21:26:2377 days ago1728681983
0x6e220Be8...CF7529Af6
0.00011456 ETH
209450462024-10-11 21:25:5977 days ago1728681959
0x6e220Be8...CF7529Af6
0.00989176 ETH
209450462024-10-11 21:25:5977 days ago1728681959
0x6e220Be8...CF7529Af6
0.00010823 ETH
209450462024-10-11 21:25:5977 days ago1728681959
0x6e220Be8...CF7529Af6
0.01 ETH
205258532024-08-14 9:03:59136 days ago1723626239
0x6e220Be8...CF7529Af6
0.00992988 ETH
205258532024-08-14 9:03:59136 days ago1723626239
0x6e220Be8...CF7529Af6
0.00007011 ETH
204251192024-07-31 7:43:47150 days ago1722411827
0x6e220Be8...CF7529Af6
0.00992183 ETH
204251192024-07-31 7:43:47150 days ago1722411827
0x6e220Be8...CF7529Af6
0.00007816 ETH
204251172024-07-31 7:43:23150 days ago1722411803
0x6e220Be8...CF7529Af6
0.01 ETH
203964602024-07-27 7:42:59154 days ago1722066179
0x6e220Be8...CF7529Af6
0.01 ETH
203961052024-07-27 6:31:11154 days ago1722061871
0x6e220Be8...CF7529Af6
0.01 ETH
203265932024-07-17 13:37:35163 days ago1721223455
0x6e220Be8...CF7529Af6
0.00988564 ETH
203265932024-07-17 13:37:35163 days ago1721223455
0x6e220Be8...CF7529Af6
0.00011435 ETH
203257192024-07-17 10:41:47163 days ago1721212907
0x6e220Be8...CF7529Af6
0.00990832 ETH
203257192024-07-17 10:41:47163 days ago1721212907
0x6e220Be8...CF7529Af6
0.00009167 ETH
203200852024-07-16 15:51:59164 days ago1721145119
0x6e220Be8...CF7529Af6
0.01 ETH
203200792024-07-16 15:50:47164 days ago1721145047
0x6e220Be8...CF7529Af6
0.00987794 ETH
203200792024-07-16 15:50:47164 days ago1721145047
0x6e220Be8...CF7529Af6
0.00012205 ETH
203124392024-07-15 14:14:11165 days ago1721052851
0x6e220Be8...CF7529Af6
0.00989799 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
VeBeacon

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
paris EvmVersion
File 1 of 14 : VeBeacon.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.4;

import "solmate/utils/SafeTransferLib.sol";

import "universal-bridge-lib/UniversalBridgeLib.sol";

import "./VeRecipient.sol";
import "./base/Structs.sol";
import "./interfaces/IVotingEscrow.sol";

/// @title VeBeacon
/// @author zefram.eth
/// @notice Broadcasts veToken balances to other chains
contract VeBeacon {
    /// -----------------------------------------------------------------------
    /// Errors
    /// -----------------------------------------------------------------------

    error VeBeacon__UserNotInitialized();

    /// -----------------------------------------------------------------------
    /// Events
    /// -----------------------------------------------------------------------

    event BroadcastVeBalance(address indexed user, uint256 indexed chainId);

    /// -----------------------------------------------------------------------
    /// Constants
    /// -----------------------------------------------------------------------

    uint256 internal constant SLOPE_CHANGES_LENGTH = 8;
    uint256 internal constant DATA_LENGTH = 4 + 8 * 32 + 32 + SLOPE_CHANGES_LENGTH * 64; // 4b selector + 8 * 32b args + 32b array length + SLOPE_CHANGES_LENGTH * 64b array content

    /// -----------------------------------------------------------------------
    /// Immutable params
    /// -----------------------------------------------------------------------

    IVotingEscrow public immutable votingEscrow;
    address public immutable recipientAddress;

    /// -----------------------------------------------------------------------
    /// Constructor
    /// -----------------------------------------------------------------------

    constructor(IVotingEscrow votingEscrow_, address recipientAddress_) {
        votingEscrow = votingEscrow_;
        recipientAddress = recipientAddress_;
    }

    /// -----------------------------------------------------------------------
    /// External functions
    /// -----------------------------------------------------------------------

    /// @notice Broadcasts a user's vetoken balance to another chain. Should use getRequiredMessageValue()
    /// to compute the msg.value required when calling this function.
    /// @param user the user address
    /// @param chainId the target chain's ID
    /// @param gasLimit the gas limit of the call to the recipient
    /// @param maxFeePerGas the max gas price used, only relevant for some chains (e.g. Arbitrum)
    function broadcastVeBalance(address user, uint256 chainId, uint256 gasLimit, uint256 maxFeePerGas)
        external
        payable
    {
        _broadcastVeBalance(user, chainId, gasLimit, maxFeePerGas);
        _refundEthBalanceIfWorthIt();
    }

    /// @notice Broadcasts a user's vetoken balance to a list of other chains. Should use getRequiredMessageValue()
    /// to compute the msg.value required when calling this function (currently only applicable to Arbitrum).
    /// @param user the user address
    /// @param chainIdList the chain ID of the target chains
    /// @param gasLimit the gas limit of each call to the recipient
    /// @param maxFeePerGas the max gas price used, only relevant for some chains (e.g. Arbitrum)
    function broadcastVeBalanceMultiple(
        address user,
        uint256[] calldata chainIdList,
        uint256 gasLimit,
        uint256 maxFeePerGas
    ) external payable {
        uint256 chainIdListLength = chainIdList.length;
        for (uint256 i; i < chainIdListLength;) {
            _broadcastVeBalance(user, chainIdList[i], gasLimit, maxFeePerGas);

            unchecked {
                ++i;
            }
        }
        _refundEthBalanceIfWorthIt();
    }

    /// @notice Broadcasts multiple users' vetoken balances to a list of other chains. Should use getRequiredMessageValue()
    /// to compute the msg.value required when calling this function (currently only applicable to Arbitrum).
    /// @param userList the user addresses
    /// @param chainIdList the chain ID of the target chains
    /// @param gasLimit the gas limit of each call to the recipient
    /// @param maxFeePerGas the max gas price used, only relevant for some chains (e.g. Arbitrum)
    function broadcastVeBalanceMultiple(
        address[] calldata userList,
        uint256[] calldata chainIdList,
        uint256 gasLimit,
        uint256 maxFeePerGas
    ) external payable {
        uint256 userListLength = userList.length;
        uint256 chainIdListLength = chainIdList.length;
        for (uint256 i; i < userListLength;) {
            for (uint256 j; j < chainIdListLength;) {
                _broadcastVeBalance(userList[i], chainIdList[j], gasLimit, maxFeePerGas);

                unchecked {
                    ++j;
                }
            }

            unchecked {
                ++i;
            }
        }
        _refundEthBalanceIfWorthIt();
    }

    /// @notice Computes the msg.value needed when calling broadcastVeBalance(). Only relevant for Arbitrum.
    /// @param chainId the target chain's ID
    /// @param gasLimit the gas limit of the call to the recipient
    /// @param maxFeePerGas the max gas price used, only relevant for some chains (e.g. Arbitrum)
    /// @return the msg.value required
    function getRequiredMessageValue(uint256 chainId, uint256 gasLimit, uint256 maxFeePerGas)
        external
        view
        returns (uint256)
    {
        return UniversalBridgeLib.getRequiredMessageValue(chainId, DATA_LENGTH, gasLimit, maxFeePerGas);
    }

    /// -----------------------------------------------------------------------
    /// Internal functions
    /// -----------------------------------------------------------------------

    function _broadcastVeBalance(address user, uint256 chainId, uint256 gasLimit, uint256 maxFeePerGas)
        internal
        virtual
    {
        bytes memory data;
        {
            // get user voting escrow data
            uint256 epoch = votingEscrow.user_point_epoch(user);
            if (epoch == 0) revert VeBeacon__UserNotInitialized();
            (int128 userBias, int128 userSlope, uint256 userTs,) = votingEscrow.user_point_history(user, epoch);

            // get global data
            epoch = votingEscrow.epoch();
            (int128 globalBias, int128 globalSlope, uint256 globalTs,) = votingEscrow.point_history(epoch);

            // fetch slope changes in the range [currentEpochStartTimestamp + 1 weeks, currentEpochStartTimestamp + (SLOPE_CHANGES_LENGTH + 1) * 1 weeks]
            uint256 currentEpochStartTimestamp = (block.timestamp / (1 weeks)) * (1 weeks);
            SlopeChange[] memory slopeChanges = new SlopeChange[](SLOPE_CHANGES_LENGTH);
            for (uint256 i; i < SLOPE_CHANGES_LENGTH;) {
                currentEpochStartTimestamp += 1 weeks;
                slopeChanges[i] = SlopeChange({
                    ts: currentEpochStartTimestamp,
                    change: votingEscrow.slope_changes(currentEpochStartTimestamp)
                });
                unchecked {
                    ++i;
                }
            }

            data = abi.encodeWithSelector(
                VeRecipient.updateVeBalance.selector,
                user,
                userBias,
                userSlope,
                userTs,
                globalBias,
                globalSlope,
                globalTs,
                slopeChanges
            );
        }

        // send data to recipient on target chain using UniversalBridgeLib
        uint256 requiredValue = UniversalBridgeLib.getRequiredMessageValue(chainId, DATA_LENGTH, gasLimit, maxFeePerGas);
        UniversalBridgeLib.sendMessage(chainId, recipientAddress, data, gasLimit, requiredValue, maxFeePerGas);

        emit BroadcastVeBalance(user, chainId);
    }

    function _refundEthBalanceIfWorthIt() internal {
        if (address(this).balance == 0) return; // early return if beacon has no balance
        if (address(this).balance < block.basefee * 21000) return; // early return if refunding ETH costs more than the refunded amount
        SafeTransferLib.safeTransferETH(msg.sender, address(this).balance);
    }
}

File 2 of 14 : SafeTransferLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {ERC20} from "../tokens/ERC20.sol";

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
            mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}

File 3 of 14 : UniversalBridgeLib.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.4;

import "./bridges/ArbitrumBridge.sol";
import "./bridges/OptimismBridge.sol";
import "./bridges/PolygonBridge.sol";
import "./bridges/ArbitraryMessageBridge.sol";

/// @title Unified library for sending messages from Ethereum to other chains and rollups
/// @author zefram.eth
/// @notice Enables sending messages from Ethereum to other chains via a single interface.
library UniversalBridgeLib {
    /// -----------------------------------------------------------------------
    /// Constants
    /// -----------------------------------------------------------------------

    uint256 internal constant DEFAULT_MAX_FEE_PER_GAS = 0.1 gwei;

    uint256 internal constant CHAINID_ARBITRUM = 42161;
    ArbitrumBridge internal constant BRIDGE_ARBITRUM = ArbitrumBridge(0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f);

    uint256 internal constant CHAINID_OPTIMISM = 10;
    OptimismBridge internal constant BRIDGE_OPTIMISM = OptimismBridge(0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1);

    uint256 internal constant CHAINID_POLYGON = 137;
    PolygonBridge internal constant BRIDGE_POLYGON = PolygonBridge(0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2);

    uint256 internal constant CHAINID_BSC = 56;
    ArbitraryMessageBridge internal constant BRIDGE_BSC =
        ArbitraryMessageBridge(0x07955be2967B655Cf52751fCE7ccC8c61EA594e2);

    uint256 internal constant CHAINID_GNOSIS = 100;
    ArbitraryMessageBridge internal constant BRIDGE_GNOSIS =
        ArbitraryMessageBridge(0x4C36d2919e407f0Cc2Ee3c993ccF8ac26d9CE64e);

    /// -----------------------------------------------------------------------
    /// Errors
    /// -----------------------------------------------------------------------

    error UniversalBridgeLib__GasLimitTooLarge();
    error UniversalBridgeLib__ChainIdNotSupported();
    error UniversalBridgeLib__MsgValueNotSupported();

    /// -----------------------------------------------------------------------
    /// Main functions
    /// -----------------------------------------------------------------------

    /// @notice Sends message to recipient on target chain with the given calldata.
    /// @dev For calls to Arbitrum, any extra msg.value above what getRequiredMessageValue() returns will
    /// be used as the msg.value of the L2 call to the recipient.
    /// @param chainId the target chain's ID
    /// @param recipient the message recipient on the target chain
    /// @param data the calldata the recipient will be called with
    /// @param gasLimit the gas limit of the call to the recipient
    /// @param value the amount of ETH to send along with the message (only supported by Arbitrum)
    function sendMessage(uint256 chainId, address recipient, bytes memory data, uint256 gasLimit, uint256 value)
        internal
    {
        sendMessage(chainId, recipient, data, gasLimit, value, DEFAULT_MAX_FEE_PER_GAS);
    }

    /// @notice Sends message to recipient on target chain with the given calldata.
    /// @dev For calls to Arbitrum, any extra msg.value above what getRequiredMessageValue() returns will
    /// be used as the msg.value of the L2 call to the recipient.
    /// @param chainId the target chain's ID
    /// @param recipient the message recipient on the target chain
    /// @param data the calldata the recipient will be called with
    /// @param gasLimit the gas limit of the call to the recipient
    /// @param value the amount of ETH to send along with the message (only supported by Arbitrum)
    /// @param maxFeePerGas the max gas price used, only relevant for some chains (e.g. Arbitrum)
    function sendMessage(
        uint256 chainId,
        address recipient,
        bytes memory data,
        uint256 gasLimit,
        uint256 value,
        uint256 maxFeePerGas
    ) internal {
        if (chainId == CHAINID_ARBITRUM) _sendMessageArbitrum(recipient, data, gasLimit, value, maxFeePerGas);
        else if (chainId == CHAINID_OPTIMISM) _sendMessageOptimism(recipient, data, gasLimit, value);
        else if (chainId == CHAINID_POLYGON) _sendMessagePolygon(recipient, data, value);
        else if (chainId == CHAINID_BSC) _sendMessageAMB(BRIDGE_BSC, recipient, data, gasLimit, value);
        else if (chainId == CHAINID_GNOSIS) _sendMessageAMB(BRIDGE_GNOSIS, recipient, data, gasLimit, value);
        else revert UniversalBridgeLib__ChainIdNotSupported();
    }

    /// @notice Computes the minimum msg.value needed when calling sendMessage()
    /// @param chainId the target chain's ID
    /// @param dataLength the length of the calldata the recipient will be called with, in bytes
    /// @param gasLimit the gas limit of the call to the recipient
    /// @return the minimum msg.value required
    function getRequiredMessageValue(uint256 chainId, uint256 dataLength, uint256 gasLimit)
        internal
        view
        returns (uint256)
    {
        return getRequiredMessageValue(chainId, dataLength, gasLimit, DEFAULT_MAX_FEE_PER_GAS);
    }

    /// @notice Computes the minimum msg.value needed when calling sendMessage()
    /// @param chainId the target chain's ID
    /// @param dataLength the length of the calldata the recipient will be called with, in bytes
    /// @param gasLimit the gas limit of the call to the recipient
    /// @param maxFeePerGas the max gas price used, only relevant for some chains (e.g. Arbitrum)
    /// @return the minimum msg.value required
    function getRequiredMessageValue(uint256 chainId, uint256 dataLength, uint256 gasLimit, uint256 maxFeePerGas)
        internal
        view
        returns (uint256)
    {
        if (chainId != CHAINID_ARBITRUM) {
            return 0;
        } else {
            uint256 submissionCost = BRIDGE_ARBITRUM.calculateRetryableSubmissionFee(dataLength, block.basefee);
            return gasLimit * maxFeePerGas + submissionCost;
        }
    }

    /// -----------------------------------------------------------------------
    /// Internal helpers for sending message to different chains
    /// -----------------------------------------------------------------------

    function _sendMessageArbitrum(
        address recipient,
        bytes memory data,
        uint256 gasLimit,
        uint256 value,
        uint256 maxFeePerGas
    ) internal {
        uint256 submissionCost = BRIDGE_ARBITRUM.calculateRetryableSubmissionFee(data.length, block.basefee);
        uint256 l2CallValue = value - submissionCost - gasLimit * maxFeePerGas;
        BRIDGE_ARBITRUM.createRetryableTicket{value: value}(
            recipient, l2CallValue, submissionCost, msg.sender, msg.sender, gasLimit, maxFeePerGas, data
        );
    }

    function _sendMessageOptimism(address recipient, bytes memory data, uint256 gasLimit, uint256 value) internal {
        if (value != 0) revert UniversalBridgeLib__MsgValueNotSupported();
        if (gasLimit > type(uint32).max) revert UniversalBridgeLib__GasLimitTooLarge();
        BRIDGE_OPTIMISM.sendMessage(recipient, data, uint32(gasLimit));
    }

    function _sendMessagePolygon(address recipient, bytes memory data, uint256 value) internal {
        if (value != 0) revert UniversalBridgeLib__MsgValueNotSupported();
        BRIDGE_POLYGON.sendMessageToChild(recipient, data);
    }

    function _sendMessageAMB(
        ArbitraryMessageBridge bridge,
        address recipient,
        bytes memory data,
        uint256 gasLimit,
        uint256 value
    ) internal {
        if (value != 0) revert UniversalBridgeLib__MsgValueNotSupported();
        if (gasLimit > bridge.maxGasPerTx()) revert UniversalBridgeLib__GasLimitTooLarge();
        bridge.requireToPassMessage(recipient, data, gasLimit);
    }
}

File 4 of 14 : VeRecipient.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.4;

import {CrossChainEnabled} from "openzeppelin-contracts/contracts/crosschain/CrossChainEnabled.sol";

import "./base/Structs.sol";
import {BoringOwnable} from "./base/BoringOwnable.sol";

/// @title VeRecipient
/// @author zefram.eth
/// @notice Recipient on non-Ethereum networks that receives data from the Ethereum beacon
/// and makes vetoken balances available on this network.
abstract contract VeRecipient is CrossChainEnabled, BoringOwnable {
    /// -----------------------------------------------------------------------
    /// Errors
    /// -----------------------------------------------------------------------

    error VeRecipient__InvalidInput();

    /// -----------------------------------------------------------------------
    /// Events
    /// -----------------------------------------------------------------------

    event UpdateVeBalance(address indexed user);
    event SetBeacon(address indexed newBeacon);

    /// -----------------------------------------------------------------------
    /// Constants
    /// -----------------------------------------------------------------------

    uint256 internal constant MAX_ITERATIONS = 255;

    /// -----------------------------------------------------------------------
    /// Storage variables
    /// -----------------------------------------------------------------------

    address public beacon;
    mapping(address => Point) public userData;
    Point public globalData;
    mapping(uint256 => int128) public slopeChanges;

    /// -----------------------------------------------------------------------
    /// Constructor
    /// -----------------------------------------------------------------------

    constructor(address beacon_, address owner_) BoringOwnable(owner_) {
        beacon = beacon_;
        emit SetBeacon(beacon_);
    }

    /// -----------------------------------------------------------------------
    /// Crosschain functions
    /// -----------------------------------------------------------------------

    /// @notice Called by VeBeacon from Ethereum via bridge to update vetoken balance & supply info.
    function updateVeBalance(
        address user,
        int128 userBias,
        int128 userSlope,
        uint256 userTs,
        int128 globalBias,
        int128 globalSlope,
        uint256 globalTs,
        SlopeChange[] calldata slopeChanges_
    ) external onlyCrossChainSender(beacon) {
        userData[user] = Point({bias: userBias, slope: userSlope, ts: userTs});
        globalData = Point({bias: globalBias, slope: globalSlope, ts: globalTs});

        uint256 slopeChangesLength = slopeChanges_.length;
        for (uint256 i; i < slopeChangesLength;) {
            slopeChanges[slopeChanges_[i].ts] = slopeChanges_[i].change;

            unchecked {
                ++i;
            }
        }

        emit UpdateVeBalance(user);
    }

    /// -----------------------------------------------------------------------
    /// Owner functions
    /// -----------------------------------------------------------------------

    /// @notice Called by owner to update the beacon address.
    /// @dev The beacon address needs to be updateable because VeBeacon needs to be redeployed
    /// when support for a new network is added.
    /// @param newBeacon The new address
    function setBeacon(address newBeacon) external onlyOwner {
        if (newBeacon == address(0)) revert VeRecipient__InvalidInput();
        beacon = newBeacon;
        emit SetBeacon(newBeacon);
    }

    /// -----------------------------------------------------------------------
    /// View functions
    /// -----------------------------------------------------------------------

    /// @notice Computes the vetoken balance of a user. Returns 0 if the user's data hasn't
    /// been broadcasted from VeBeacon. Exhibits the same time-decay behavior as regular
    /// VotingEscrow contracts.
    /// @param user The user address to query
    /// @return The user's vetoken balance.
    function balanceOf(address user) external view returns (uint256) {
        // storage loads
        Point memory u = userData[user];

        // compute vetoken balance
        int256 veBalance = u.bias - u.slope * int128(int256(block.timestamp - u.ts));
        if (veBalance < 0) veBalance = 0;
        return uint256(veBalance);
    }

    /// @notice Computes the total supply of the vetoken. Returns 0 if data hasn't
    /// been broadcasted from VeBeacon. Exhibits the same time-decay behavior as regular
    /// VotingEscrow contracts.
    /// @dev The value may diverge from the correct value if `updateVeBalance()` hasn't been
    /// called for 8 consecutive epochs (~2 months). This is because we limit the size of each
    /// slopeChanges update to limit gas costs.
    /// @return The vetoken's total supply
    function totalSupply() external view returns (uint256) {
        Point memory g = globalData;
        uint256 ti = (g.ts / (1 weeks)) * (1 weeks);
        for (uint256 i; i < MAX_ITERATIONS;) {
            ti += 1 weeks;
            int128 slopeChange;
            if (ti > block.timestamp) {
                ti = block.timestamp;
            } else {
                slopeChange = slopeChanges[ti];
            }
            g.bias -= g.slope * int128(int256(ti - g.ts));
            if (ti == block.timestamp) break;
            g.slope += slopeChange;
            g.ts = ti;

            unchecked {
                ++i;
            }
        }

        if (g.bias < 0) g.bias = 0;
        return uint256(uint128(g.bias));
    }

    /// @notice Returns the timestamp a user's vetoken position was last updated. Returns 0 if the user's data
    /// has never been broadcasted.
    /// @dev Added for compatibility with kick() in gauge contracts.
    /// @param user The user's address
    /// @return The last update timestamp
    function user_point_history__ts(address user, uint256 /*epoch*/ ) external view returns (uint256) {
        return userData[user].ts;
    }

    /// @notice Just returns 0.
    /// @dev Added for compatibility with kick() in gauge contracts.
    function user_point_epoch(address /*user*/ ) external pure returns (uint256) {
        return 0;
    }
}

File 5 of 14 : Structs.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.4;

struct SlopeChange {
    uint256 ts;
    int128 change;
}

struct Point {
    int128 bias;
    int128 slope;
    uint256 ts;
}

File 6 of 14 : IVotingEscrow.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.11;
pragma abicoder v2;

interface IVotingEscrow {
    struct LockedBalance {
        int128 amount;
        uint256 end;
    }

    function change_pending_admin(address addr) external;

    function claim_admin() external;

    function commit_smart_wallet_checker(address addr) external;

    function apply_smart_wallet_checker() external;

    function get_last_user_slope(address addr) external view returns (int128);

    function user_point_history__ts(address _addr, uint256 _idx) external view returns (uint256);

    function locked__end(address _addr) external view returns (uint256);

    function checkpoint() external;

    function deposit_for(address _addr, uint256 _value) external;

    function create_lock(uint256 _value, uint256 _unlock_time) external;

    function increase_amount(uint256 _value) external;

    function increase_unlock_time(uint256 _unlock_time) external;

    function withdraw() external;

    function balanceOf(address addr) external view returns (uint256);

    function balanceOf(address addr, uint256 _t) external view returns (uint256);

    function balanceOfAt(address addr, uint256 _block) external view returns (uint256);

    function totalSupply() external view returns (uint256);

    function totalSupply(uint256 t) external view returns (uint256);

    function totalSupplyAt(uint256 _block) external view returns (uint256);

    function changeController(address _newController) external;

    function token() external view returns (address);

    function supply() external view returns (uint256);

    function locked(address addr) external view returns (LockedBalance memory);

    function epoch() external view returns (uint256);

    function point_history(uint256 arg0) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk);

    function user_point_history(address arg0, uint256 arg1)
        external
        view
        returns (int128 bias, int128 slope, uint256 ts, uint256 blk);

    function user_point_epoch(address arg0) external view returns (uint256);

    function slope_changes(uint256 arg0) external view returns (int128);

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

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

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

    function decimals() external view returns (uint256);

    function future_smart_wallet_checker() external view returns (address);

    function smart_wallet_checker() external view returns (address);

    function admin() external view returns (address);

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

File 7 of 14 : ERC20.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

File 8 of 14 : ArbitrumBridge.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.9 <0.9.0;

interface ArbitrumBridge {
    /**
     * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
     * @dev all msg.value will deposited to callValueRefundAddress on L2
     * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
     * @param to destination L2 contract address
     * @param l2CallValue call value for retryable L2 message
     * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
     * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
     * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
     * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
     * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
     * @param data ABI encoded data of L2 message
     * @return unique message number of the retryable transaction
     */
    function createRetryableTicket(
        address to,
        uint256 l2CallValue,
        uint256 maxSubmissionCost,
        address excessFeeRefundAddress,
        address callValueRefundAddress,
        uint256 gasLimit,
        uint256 maxFeePerGas,
        bytes calldata data
    ) external payable returns (uint256);

    /**
     * @notice Get the L1 fee for submitting a retryable
     * @dev This fee can be paid by funds already in the L2 aliased address or by the current message value
     * @dev This formula may change in the future, to future proof your code query this method instead of inlining!!
     * @param dataLength The length of the retryable's calldata, in bytes
     * @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used
     */
    function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) external view returns (uint256);
}

File 9 of 14 : OptimismBridge.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.9 <0.9.0;

interface OptimismBridge {
    function sendMessage(address target, bytes calldata message, uint32 gasLimit) external;
}

File 10 of 14 : PolygonBridge.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.9 <0.9.0;

interface PolygonBridge {
    function sendMessageToChild(address receiver, bytes calldata data) external;
}

File 11 of 14 : ArbitraryMessageBridge.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.9 <0.9.0;

interface ArbitraryMessageBridge {
    function maxGasPerTx() external view returns (uint256);
    function requireToPassMessage(address target, bytes calldata data, uint256 gas) external returns (bytes32);
}

File 12 of 14 : CrossChainEnabled.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/CrossChainEnabled.sol)

pragma solidity ^0.8.4;

import "./errors.sol";

/**
 * @dev Provides information for building cross-chain aware contracts. This
 * abstract contract provides accessors and modifiers to control the execution
 * flow when receiving cross-chain messages.
 *
 * Actual implementations of cross-chain aware contracts, which are based on
 * this abstraction, will  have to inherit from a bridge-specific
 * specialization. Such specializations are provided under
 * `crosschain/<chain>/CrossChainEnabled<chain>.sol`.
 *
 * _Available since v4.6._
 */
abstract contract CrossChainEnabled {
    /**
     * @dev Throws if the current function call is not the result of a
     * cross-chain execution.
     */
    modifier onlyCrossChain() {
        if (!_isCrossChain()) revert NotCrossChainCall();
        _;
    }

    /**
     * @dev Throws if the current function call is not the result of a
     * cross-chain execution initiated by `account`.
     */
    modifier onlyCrossChainSender(address expected) {
        address actual = _crossChainSender();
        if (expected != actual) revert InvalidCrossChainSender(actual, expected);
        _;
    }

    /**
     * @dev Returns whether the current function call is the result of a
     * cross-chain message.
     */
    function _isCrossChain() internal view virtual returns (bool);

    /**
     * @dev Returns the address of the sender of the cross-chain message that
     * triggered the current function call.
     *
     * IMPORTANT: Should revert with `NotCrossChainCall` if the current function
     * call is not the result of a cross-chain message.
     */
    function _crossChainSender() internal view virtual returns (address);
}

File 13 of 14 : BoringOwnable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol
// Simplified by BoringCrypto

contract BoringOwnableData {
    address public owner;
    address public pendingOwner;
}

contract BoringOwnable is BoringOwnableData {
    error BoringOwnable__ZeroAddress();
    error BoringOwnable__NotPendingOwner();
    error BoringOwnable__NotOwner();

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

    constructor(address owner_) {
        owner = owner_;
        emit OwnershipTransferred(address(0), owner_);
    }

    /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.
    /// Can only be invoked by the current `owner`.
    /// @param newOwner Address of the new owner.
    /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.
    /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.
    function transferOwnership(address newOwner, bool direct, bool renounce) public onlyOwner {
        if (direct) {
            // Checks
            if (newOwner == address(0) && !renounce) revert BoringOwnable__ZeroAddress();

            // Effects
            emit OwnershipTransferred(owner, newOwner);
            owner = newOwner;
            pendingOwner = address(0);
        } else {
            // Effects
            pendingOwner = newOwner;
        }
    }

    /// @notice Needs to be called by `pendingOwner` to claim ownership.
    function claimOwnership() public {
        address _pendingOwner = pendingOwner;

        // Checks
        if (msg.sender != _pendingOwner) revert BoringOwnable__NotPendingOwner();

        // Effects
        emit OwnershipTransferred(owner, _pendingOwner);
        owner = _pendingOwner;
        pendingOwner = address(0);
    }

    /// @notice Only allows the `owner` to execute the function.
    modifier onlyOwner() {
        if (msg.sender != owner) revert BoringOwnable__NotOwner();
        _;
    }
}

File 14 of 14 : errors.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/errors.sol)

pragma solidity ^0.8.4;

error NotCrossChainCall();
error InvalidCrossChainSender(address actual, address expected);

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IVotingEscrow","name":"votingEscrow_","type":"address"},{"internalType":"address","name":"recipientAddress_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"UniversalBridgeLib__ChainIdNotSupported","type":"error"},{"inputs":[],"name":"UniversalBridgeLib__GasLimitTooLarge","type":"error"},{"inputs":[],"name":"UniversalBridgeLib__MsgValueNotSupported","type":"error"},{"inputs":[],"name":"VeBeacon__UserNotInitialized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"BroadcastVeBalance","type":"event"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"}],"name":"broadcastVeBalance","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256[]","name":"chainIdList","type":"uint256[]"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"}],"name":"broadcastVeBalanceMultiple","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"userList","type":"address[]"},{"internalType":"uint256[]","name":"chainIdList","type":"uint256[]"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"}],"name":"broadcastVeBalanceMultiple","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"}],"name":"getRequiredMessageValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"recipientAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingEscrow","outputs":[{"internalType":"contract IVotingEscrow","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60c0346100cb57601f6115d538819003918201601f19168301916001600160401b038311848410176100d05780849260409485528339810103126100cb5780516001600160a01b039182821682036100cb576020015191821682036100cb5760805260a0526040516114ee90816100e782396080518181816103450152818161059901528181610637015281816106ae015281816107270152611087015260a0518181816101f70152818161096601528181610b1c01528181610c8701528181610e060152610fa60152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe60808060405260048036101561001457600080fd5b600091823560e01c9081634f2bfe5b146102fb57508063559b953f1461026a578063561064171461021b5780635aff5999146101ac5780637cd1fc391461015e5763df2980181461006457600080fd5b60807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015a5767ffffffffffffffff8135818111610156576100ad9036908401610391565b919092602435918211610152576100c691369101610391565b60643593916044359190865b8581106100e557876100e26112f0565b80f35b875b8381106100f757506001016100d2565b61010882888899949a9b97986103c2565b3573ffffffffffffffffffffffffffffffffffffffff8116810361014e57906101418a8860019461013a858a8a6103c2565b3590610535565b01959493979690956100e7565b8580fd5b8480fd5b8380fd5b5080fd5b5090346101a95760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a95760206101a16044356024358535611380565b604051908152f35b80fd5b82346101a957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b8260807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a957610262610251610369565b606435906044359060243590610535565b6100e26112f0565b509060807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a95761029e610369565b9160243567ffffffffffffffff81116102f7576102bd91369101610391565b9260443560643591845b8681106102d757856100e26112f0565b806102f185856102ea6001958c8b6103c2565b3586610535565b016102c7565b8280fd5b83903461015a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015a5760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361038c57565b600080fd5b9181601f8401121561038c5782359167ffffffffffffffff831161038c576020808501948460051b01011161038c57565b91908110156103d25760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8181029291811591840414171561041457565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6040810190811067ffffffffffffffff82111761045f57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff811161045f57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761045f57604052565b519081600f0b820361038c57565b919082608091031261038c57610506826104e3565b91610513602082016104e3565b916060604083015192015190565b80518210156103d25760209160051b010190565b90926040517f010ae75700000000000000000000000000000000000000000000000000000000815260009373ffffffffffffffffffffffffffffffffffffffff8416600483015260208260248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9182156112e55785926112b1575b50811561128757604051917f28d09d4700000000000000000000000000000000000000000000000000000000835273ffffffffffffffffffffffffffffffffffffffff851660048401526024830152608091828160448173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa8015610eea57869387928892611260575b506040517f900cf0cf00000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561121f57899161122a575b50604051907fd1febfb90000000000000000000000000000000000000000000000000000000082526004820152818160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa92831561121f5789918a938b956111e8575b505062093a80420462093a8081029080820462093a8014901517156111bb5794604051958661012081011067ffffffffffffffff6101208901111761118e576101208701604052600887528b5b610100811061116a57508b905b6008821061102e575050604051977f6a5df3af0000000000000000000000000000000000000000000000000000000060208a015273ffffffffffffffffffffffffffffffffffffffff8b1660248a0152600f0b6044890152600f0b60648801526084870152600f0b60a4860152600f0b60c485015260e4840152610100610104840152828151918261012483015260206101448301910192885b8181106110065750506108899250037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018452836104a2565b610894838288611380565b61a4b18703610a9757825192604051937fa66b327d0000000000000000000000000000000000000000000000000000000085526004850152486024850152602084604481734dbd4fc535ac27206064b68ffcf827b0a60bab3f5afa908115610a8c578791610a57575b602094506109be61092161091184866114ab565b61091b8988610401565b906114ab565b91604051978896879586957f679b6ded00000000000000000000000000000000000000000000000000000000875273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660048801526024870152604486015233606486015233608486015260a485015260c484015261010060e484015261010483019061144d565b0391734dbd4fc535ac27206064b68ffcf827b0a60bab3f5af18015610a4c57610a21575b5073ffffffffffffffffffffffffffffffffffffffff7f86b71803ac02486394b26761e170eecdc490c9fb8c07d778622c30def3d85cdc915b169180a3565b602090813d8311610a45575b610a3781836104a2565b8101031261038c57386109e2565b503d610a2d565b6040513d85823e3d90fd5b90506020843d602011610a84575b81610a72602093836104a2565b8101031261038c5760209351906108fd565b3d9150610a65565b6040513d89823e3d90fd5b909250600a8603610c1157610be75763ffffffff90818311610bbd577325ace71c97b33cc4729cf772ae268934f7ab5fa190813b1561014e5790610b5286809493604051968795869485937f3dbb202b00000000000000000000000000000000000000000000000000000000855273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016600486015260606024860152606485019061144d565b9116604483015203925af18015610a4c57908391610ba9575b505073ffffffffffffffffffffffffffffffffffffffff7f86b71803ac02486394b26761e170eecdc490c9fb8c07d778622c30def3d85cdc91610a1b565b610bb29061048e565b61015a578138610b6b565b60046040517f31b5f33c000000000000000000000000000000000000000000000000000000008152fd5b60046040517fe9b7bbde000000000000000000000000000000000000000000000000000000008152fd5b909160898603610d525750610be75773fe5e5d361b2ad62c541bab87c45a0b9b018389a290813b1561015657610cbd849283926040519485809481937fb472047700000000000000000000000000000000000000000000000000000000835273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016600484015260406024840152604483019061144d565b03925af18015610a4c57610d09575b5073ffffffffffffffffffffffffffffffffffffffff7f86b71803ac02486394b26761e170eecdc490c9fb8c07d778622c30def3d85cdc91610a1b565b7f86b71803ac02486394b26761e170eecdc490c9fb8c07d778622c30def3d85cdc9192610d4a73ffffffffffffffffffffffffffffffffffffffff9261048e565b929150610ccc565b919060388603610ef557610be757604051907fe5789d030000000000000000000000000000000000000000000000000000000082527307955be2967b655cf52751fce7ccc8c61ea594e291602081600481865afa908115610eea578691610eb8575b508311610bbd57602091610e3c91866040518096819582947fdc8601b300000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016600485015260606024850152606484019061144d565b90604483015203925af18015610a4c57610e8d575073ffffffffffffffffffffffffffffffffffffffff7f86b71803ac02486394b26761e170eecdc490c9fb8c07d778622c30def3d85cdc91610a1b565b602090813d8311610eb1575b610ea381836104a2565b8101031261015a5738610ccc565b503d610e99565b90506020813d602011610ee2575b81610ed3602093836104a2565b8101031261014e575138610db4565b3d9150610ec6565b6040513d88823e3d90fd5b60648603610fdc57610be757604051907fe5789d03000000000000000000000000000000000000000000000000000000008252734c36d2919e407f0cc2ee3c993ccf8ac26d9ce64e91602081600481865afa908115610eea578691610eb857508311610bbd57602091610e3c91866040518096819582947fdc8601b300000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016600485015260606024850152606484019061144d565b60046040517f9cd5c02a000000000000000000000000000000000000000000000000000000008152fd5b845180518452602090810151600f0b818501529094019386935060409092019160010161084f565b62093a80810180911161113d578091604051917f7119748400000000000000000000000000000000000000000000000000000000835280600484015260208360248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa8015611130578f906110ee575b60019350604051916110c783610443565b8252600f0b60208201526110db828b610521565b526110e6818a610521565b5001906107b5565b5090916020813d602011611128575b8161110a602093836104a2565b81010312611124579061111f600193926104e3565b6110b6565b8e80fd5b3d91506110fd565b8f604051903d90823e3d90fd5b60248d7f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6020908d6040519061117b82610443565b8082528382015282828b010152016107a8565b60248c7f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60248b7f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b919450915061120c9250803d10611218575b61120481836104a2565b8101906104f1565b5091909192388061075b565b503d6111fa565b6040513d8b823e3d90fd5b90506020813d602011611258575b81611245602093836104a2565b810103126112545751386106de565b8880fd5b3d9150611238565b915080945061127b92503d85116112185761120481836104a2565b5091939091903861066a565b60046040517f50ba2d05000000000000000000000000000000000000000000000000000000008152fd5b9091506020813d6020116112dd575b816112cd602093836104a2565b81010312610152575190386105c9565b3d91506112c0565b6040513d87823e3d90fd5b471561137e574761520890814802914883041448151715610414571061137e57600080808047335af11561132057565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152fd5b565b90919061a4b114611392575050600090565b604051907fa66b327d0000000000000000000000000000000000000000000000000000000082526103246004830152486024830152602082604481734dbd4fc535ac27206064b68ffcf827b0a60bab3f5afa9182156114415760009261140b575b506113fe9192610401565b9081018091116104145790565b91506020823d602011611439575b81611426602093836104a2565b8101031261038c576113fe9151916113f3565b3d9150611419565b6040513d6000823e3d90fd5b919082519283825260005b8481106114975750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201611458565b919082039182116104145756fea2646970667358221220c76f0d2660a82ef81e07fbc9a2d7a6918d720bfc322015f0729444b8eabc767864736f6c634300081800330000000000000000000000000ab4bc35ef33089b9082ca7bb8657d7c4e819a1a000000000000000000000000c1a6db6793967ff7fb7f211e044a4c285a0eb7fb

Deployed Bytecode

0x60808060405260048036101561001457600080fd5b600091823560e01c9081634f2bfe5b146102fb57508063559b953f1461026a578063561064171461021b5780635aff5999146101ac5780637cd1fc391461015e5763df2980181461006457600080fd5b60807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015a5767ffffffffffffffff8135818111610156576100ad9036908401610391565b919092602435918211610152576100c691369101610391565b60643593916044359190865b8581106100e557876100e26112f0565b80f35b875b8381106100f757506001016100d2565b61010882888899949a9b97986103c2565b3573ffffffffffffffffffffffffffffffffffffffff8116810361014e57906101418a8860019461013a858a8a6103c2565b3590610535565b01959493979690956100e7565b8580fd5b8480fd5b8380fd5b5080fd5b5090346101a95760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a95760206101a16044356024358535611380565b604051908152f35b80fd5b82346101a957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a957602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c1a6db6793967ff7fb7f211e044a4c285a0eb7fb168152f35b8260807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a957610262610251610369565b606435906044359060243590610535565b6100e26112f0565b509060807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a95761029e610369565b9160243567ffffffffffffffff81116102f7576102bd91369101610391565b9260443560643591845b8681106102d757856100e26112f0565b806102f185856102ea6001958c8b6103c2565b3586610535565b016102c7565b8280fd5b83903461015a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015a5760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000ab4bc35ef33089b9082ca7bb8657d7c4e819a1a168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361038c57565b600080fd5b9181601f8401121561038c5782359167ffffffffffffffff831161038c576020808501948460051b01011161038c57565b91908110156103d25760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8181029291811591840414171561041457565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6040810190811067ffffffffffffffff82111761045f57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff811161045f57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761045f57604052565b519081600f0b820361038c57565b919082608091031261038c57610506826104e3565b91610513602082016104e3565b916060604083015192015190565b80518210156103d25760209160051b010190565b90926040517f010ae75700000000000000000000000000000000000000000000000000000000815260009373ffffffffffffffffffffffffffffffffffffffff8416600483015260208260248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000ab4bc35ef33089b9082ca7bb8657d7c4e819a1a165afa9182156112e55785926112b1575b50811561128757604051917f28d09d4700000000000000000000000000000000000000000000000000000000835273ffffffffffffffffffffffffffffffffffffffff851660048401526024830152608091828160448173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000ab4bc35ef33089b9082ca7bb8657d7c4e819a1a165afa8015610eea57869387928892611260575b506040517f900cf0cf00000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000ab4bc35ef33089b9082ca7bb8657d7c4e819a1a165afa90811561121f57899161122a575b50604051907fd1febfb90000000000000000000000000000000000000000000000000000000082526004820152818160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000ab4bc35ef33089b9082ca7bb8657d7c4e819a1a165afa92831561121f5789918a938b956111e8575b505062093a80420462093a8081029080820462093a8014901517156111bb5794604051958661012081011067ffffffffffffffff6101208901111761118e576101208701604052600887528b5b610100811061116a57508b905b6008821061102e575050604051977f6a5df3af0000000000000000000000000000000000000000000000000000000060208a015273ffffffffffffffffffffffffffffffffffffffff8b1660248a0152600f0b6044890152600f0b60648801526084870152600f0b60a4860152600f0b60c485015260e4840152610100610104840152828151918261012483015260206101448301910192885b8181106110065750506108899250037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018452836104a2565b610894838288611380565b61a4b18703610a9757825192604051937fa66b327d0000000000000000000000000000000000000000000000000000000085526004850152486024850152602084604481734dbd4fc535ac27206064b68ffcf827b0a60bab3f5afa908115610a8c578791610a57575b602094506109be61092161091184866114ab565b61091b8988610401565b906114ab565b91604051978896879586957f679b6ded00000000000000000000000000000000000000000000000000000000875273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c1a6db6793967ff7fb7f211e044a4c285a0eb7fb1660048801526024870152604486015233606486015233608486015260a485015260c484015261010060e484015261010483019061144d565b0391734dbd4fc535ac27206064b68ffcf827b0a60bab3f5af18015610a4c57610a21575b5073ffffffffffffffffffffffffffffffffffffffff7f86b71803ac02486394b26761e170eecdc490c9fb8c07d778622c30def3d85cdc915b169180a3565b602090813d8311610a45575b610a3781836104a2565b8101031261038c57386109e2565b503d610a2d565b6040513d85823e3d90fd5b90506020843d602011610a84575b81610a72602093836104a2565b8101031261038c5760209351906108fd565b3d9150610a65565b6040513d89823e3d90fd5b909250600a8603610c1157610be75763ffffffff90818311610bbd577325ace71c97b33cc4729cf772ae268934f7ab5fa190813b1561014e5790610b5286809493604051968795869485937f3dbb202b00000000000000000000000000000000000000000000000000000000855273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c1a6db6793967ff7fb7f211e044a4c285a0eb7fb16600486015260606024860152606485019061144d565b9116604483015203925af18015610a4c57908391610ba9575b505073ffffffffffffffffffffffffffffffffffffffff7f86b71803ac02486394b26761e170eecdc490c9fb8c07d778622c30def3d85cdc91610a1b565b610bb29061048e565b61015a578138610b6b565b60046040517f31b5f33c000000000000000000000000000000000000000000000000000000008152fd5b60046040517fe9b7bbde000000000000000000000000000000000000000000000000000000008152fd5b909160898603610d525750610be75773fe5e5d361b2ad62c541bab87c45a0b9b018389a290813b1561015657610cbd849283926040519485809481937fb472047700000000000000000000000000000000000000000000000000000000835273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c1a6db6793967ff7fb7f211e044a4c285a0eb7fb16600484015260406024840152604483019061144d565b03925af18015610a4c57610d09575b5073ffffffffffffffffffffffffffffffffffffffff7f86b71803ac02486394b26761e170eecdc490c9fb8c07d778622c30def3d85cdc91610a1b565b7f86b71803ac02486394b26761e170eecdc490c9fb8c07d778622c30def3d85cdc9192610d4a73ffffffffffffffffffffffffffffffffffffffff9261048e565b929150610ccc565b919060388603610ef557610be757604051907fe5789d030000000000000000000000000000000000000000000000000000000082527307955be2967b655cf52751fce7ccc8c61ea594e291602081600481865afa908115610eea578691610eb8575b508311610bbd57602091610e3c91866040518096819582947fdc8601b300000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c1a6db6793967ff7fb7f211e044a4c285a0eb7fb16600485015260606024850152606484019061144d565b90604483015203925af18015610a4c57610e8d575073ffffffffffffffffffffffffffffffffffffffff7f86b71803ac02486394b26761e170eecdc490c9fb8c07d778622c30def3d85cdc91610a1b565b602090813d8311610eb1575b610ea381836104a2565b8101031261015a5738610ccc565b503d610e99565b90506020813d602011610ee2575b81610ed3602093836104a2565b8101031261014e575138610db4565b3d9150610ec6565b6040513d88823e3d90fd5b60648603610fdc57610be757604051907fe5789d03000000000000000000000000000000000000000000000000000000008252734c36d2919e407f0cc2ee3c993ccf8ac26d9ce64e91602081600481865afa908115610eea578691610eb857508311610bbd57602091610e3c91866040518096819582947fdc8601b300000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c1a6db6793967ff7fb7f211e044a4c285a0eb7fb16600485015260606024850152606484019061144d565b60046040517f9cd5c02a000000000000000000000000000000000000000000000000000000008152fd5b845180518452602090810151600f0b818501529094019386935060409092019160010161084f565b62093a80810180911161113d578091604051917f7119748400000000000000000000000000000000000000000000000000000000835280600484015260208360248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000ab4bc35ef33089b9082ca7bb8657d7c4e819a1a165afa8015611130578f906110ee575b60019350604051916110c783610443565b8252600f0b60208201526110db828b610521565b526110e6818a610521565b5001906107b5565b5090916020813d602011611128575b8161110a602093836104a2565b81010312611124579061111f600193926104e3565b6110b6565b8e80fd5b3d91506110fd565b8f604051903d90823e3d90fd5b60248d7f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6020908d6040519061117b82610443565b8082528382015282828b010152016107a8565b60248c7f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60248b7f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b919450915061120c9250803d10611218575b61120481836104a2565b8101906104f1565b5091909192388061075b565b503d6111fa565b6040513d8b823e3d90fd5b90506020813d602011611258575b81611245602093836104a2565b810103126112545751386106de565b8880fd5b3d9150611238565b915080945061127b92503d85116112185761120481836104a2565b5091939091903861066a565b60046040517f50ba2d05000000000000000000000000000000000000000000000000000000008152fd5b9091506020813d6020116112dd575b816112cd602093836104a2565b81010312610152575190386105c9565b3d91506112c0565b6040513d87823e3d90fd5b471561137e574761520890814802914883041448151715610414571061137e57600080808047335af11561132057565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152fd5b565b90919061a4b114611392575050600090565b604051907fa66b327d0000000000000000000000000000000000000000000000000000000082526103246004830152486024830152602082604481734dbd4fc535ac27206064b68ffcf827b0a60bab3f5afa9182156114415760009261140b575b506113fe9192610401565b9081018091116104145790565b91506020823d602011611439575b81611426602093836104a2565b8101031261038c576113fe9151916113f3565b3d9150611419565b6040513d6000823e3d90fd5b919082519283825260005b8481106114975750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201611458565b919082039182116104145756fea2646970667358221220c76f0d2660a82ef81e07fbc9a2d7a6918d720bfc322015f0729444b8eabc767864736f6c63430008180033

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

0000000000000000000000000ab4bc35ef33089b9082ca7bb8657d7c4e819a1a000000000000000000000000c1a6db6793967ff7fb7f211e044a4c285a0eb7fb

-----Decoded View---------------
Arg [0] : votingEscrow_ (address): 0x0aB4bC35Ef33089B9082Ca7BB8657D7c4E819a1A
Arg [1] : recipientAddress_ (address): 0xC1A6Db6793967Ff7fb7f211E044A4c285A0eB7FB

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000ab4bc35ef33089b9082ca7bb8657d7c4e819a1a
Arg [1] : 000000000000000000000000c1a6db6793967ff7fb7f211e044a4c285a0eb7fb


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.