Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 58 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Broadcast Ve Bal... | 21418558 | 11 days ago | IN | 0.01 ETH | 0.00298778 | ||||
Broadcast Ve Bal... | 20981182 | 72 days ago | IN | 0.01 ETH | 0.0018334 | ||||
Broadcast Ve Bal... | 20945050 | 77 days ago | IN | 0.01 ETH | 0.00257229 | ||||
Broadcast Ve Bal... | 20945048 | 77 days ago | IN | 0.01 ETH | 0.00220258 | ||||
Broadcast Ve Bal... | 20945046 | 77 days ago | IN | 0.01 ETH | 0.00180854 | ||||
Broadcast Ve Bal... | 20945046 | 77 days ago | IN | 0.01 ETH | 0.00218873 | ||||
Broadcast Ve Bal... | 20525853 | 136 days ago | IN | 0.01 ETH | 0.00091437 | ||||
Broadcast Ve Bal... | 20425119 | 150 days ago | IN | 0.01 ETH | 0.00088421 | ||||
Broadcast Ve Bal... | 20425117 | 150 days ago | IN | 0.01 ETH | 0.00147395 | ||||
Broadcast Ve Bal... | 20396460 | 154 days ago | IN | 0.01 ETH | 0.0010347 | ||||
Broadcast Ve Bal... | 20396105 | 154 days ago | IN | 0.01 ETH | 0.00101812 | ||||
Broadcast Ve Bal... | 20326593 | 163 days ago | IN | 0.01 ETH | 0.00220037 | ||||
Broadcast Ve Bal... | 20325719 | 163 days ago | IN | 0.01 ETH | 0.0014864 | ||||
Broadcast Ve Bal... | 20320085 | 164 days ago | IN | 0.01 ETH | 0.00245283 | ||||
Broadcast Ve Bal... | 20320079 | 164 days ago | IN | 0.01 ETH | 0.00224701 | ||||
Broadcast Ve Bal... | 20312439 | 165 days ago | IN | 0.01 ETH | 0.00179319 | ||||
Broadcast Ve Bal... | 20290310 | 168 days ago | IN | 0.01 ETH | 0.00143147 | ||||
Broadcast Ve Bal... | 20288184 | 169 days ago | IN | 0.01 ETH | 0.00037443 | ||||
Broadcast Ve Bal... | 20288181 | 169 days ago | IN | 0.01 ETH | 0.00114431 | ||||
Broadcast Ve Bal... | 20287985 | 169 days ago | IN | 0.01 ETH | 0.00043732 | ||||
Broadcast Ve Bal... | 20285987 | 169 days ago | IN | 0.01 ETH | 0.0008313 | ||||
Broadcast Ve Bal... | 20282366 | 170 days ago | IN | 0.01 ETH | 0.00299908 | ||||
Broadcast Ve Bal... | 20274828 | 171 days ago | IN | 0.01 ETH | 0.00097422 | ||||
Broadcast Ve Bal... | 20269506 | 171 days ago | IN | 0.01 ETH | 0.00165874 | ||||
Broadcast Ve Bal... | 20229216 | 177 days ago | IN | 0.01 ETH | 0.00085285 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21418558 | 11 days ago | 0.00985424 ETH | ||||
21418558 | 11 days ago | 0.00014575 ETH | ||||
20981182 | 72 days ago | 0.00989157 ETH | ||||
20981182 | 72 days ago | 0.00010842 ETH | ||||
20945050 | 77 days ago | 0.01 ETH | ||||
20945048 | 77 days ago | 0.00988543 ETH | ||||
20945048 | 77 days ago | 0.00011456 ETH | ||||
20945046 | 77 days ago | 0.00989176 ETH | ||||
20945046 | 77 days ago | 0.00010823 ETH | ||||
20945046 | 77 days ago | 0.01 ETH | ||||
20525853 | 136 days ago | 0.00992988 ETH | ||||
20525853 | 136 days ago | 0.00007011 ETH | ||||
20425119 | 150 days ago | 0.00992183 ETH | ||||
20425119 | 150 days ago | 0.00007816 ETH | ||||
20425117 | 150 days ago | 0.01 ETH | ||||
20396460 | 154 days ago | 0.01 ETH | ||||
20396105 | 154 days ago | 0.01 ETH | ||||
20326593 | 163 days ago | 0.00988564 ETH | ||||
20326593 | 163 days ago | 0.00011435 ETH | ||||
20325719 | 163 days ago | 0.00990832 ETH | ||||
20325719 | 163 days ago | 0.00009167 ETH | ||||
20320085 | 164 days ago | 0.01 ETH | ||||
20320079 | 164 days ago | 0.00987794 ETH | ||||
20320079 | 164 days ago | 0.00012205 ETH | ||||
20312439 | 165 days ago | 0.00989799 ETH |
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
Contract Source Code (Solidity Standard Json-Input format)
// 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); } }
// 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"); } }
// 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); } }
// 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; } }
// 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; }
// 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); }
// 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); } }
// 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); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.9 <0.9.0; interface OptimismBridge { function sendMessage(address target, bytes calldata message, uint32 gasLimit) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.9 <0.9.0; interface PolygonBridge { function sendMessageToChild(address receiver, bytes calldata data) external; }
// 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); }
// 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); }
// 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(); _; } }
// 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);
{ "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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.