Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
L2ToL1MessagePasser
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 999999 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Types } from "src/libraries/Types.sol";
import { Hashing } from "src/libraries/Hashing.sol";
import { Encoding } from "src/libraries/Encoding.sol";
import { Burn } from "src/libraries/Burn.sol";
import { ISemver } from "src/universal/interfaces/ISemver.sol";
/// @custom:proxied true
/// @custom:predeploy 0x4200000000000000000000000000000000000016
/// @title L2ToL1MessagePasser
/// @notice The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from
/// L2 to L1 can be stored. The storage root of this contract is pulled up to the top level
/// of the L2 output to reduce the cost of proving the existence of sent messages.
contract L2ToL1MessagePasser is ISemver {
/// @notice The L1 gas limit set when eth is withdrawn using the receive() function.
uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;
/// @notice The current message version identifier.
uint16 public constant MESSAGE_VERSION = 1;
/// @notice Includes the message hashes for all withdrawals
mapping(bytes32 => bool) public sentMessages;
/// @notice A unique value hashed with each withdrawal.
uint240 internal msgNonce;
/// @notice Emitted any time a withdrawal is initiated.
/// @param nonce Unique value corresponding to each withdrawal.
/// @param sender The L2 account address which initiated the withdrawal.
/// @param target The L1 account address the call will be send to.
/// @param value The ETH value submitted for withdrawal, to be forwarded to the target.
/// @param gasLimit The minimum amount of gas that must be provided when withdrawing.
/// @param data The data to be forwarded to the target on L1.
/// @param withdrawalHash The hash of the withdrawal.
event MessagePassed(
uint256 indexed nonce,
address indexed sender,
address indexed target,
uint256 value,
uint256 gasLimit,
bytes data,
bytes32 withdrawalHash
);
/// @notice Emitted when the balance of this contract is burned.
/// @param amount Amount of ETh that was burned.
event WithdrawerBalanceBurnt(uint256 indexed amount);
/// @custom:semver 1.1.1-beta.1
string public constant version = "1.1.1-beta.1";
/// @notice Allows users to withdraw ETH by sending directly to this contract.
receive() external payable {
initiateWithdrawal(msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(""));
}
/// @notice Removes all ETH held by this contract from the state. Used to prevent the amount of
/// ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to
/// create a contract and self-destruct it to itself. Anyone can call this function. Not
/// incentivized since this function is very cheap.
function burn() external {
uint256 balance = address(this).balance;
Burn.eth(balance);
emit WithdrawerBalanceBurnt(balance);
}
/// @notice Sends a message from L2 to L1.
/// @param _target Address to call on L1 execution.
/// @param _gasLimit Minimum gas limit for executing the message on L1.
/// @param _data Data to forward to L1 target.
function initiateWithdrawal(address _target, uint256 _gasLimit, bytes memory _data) public payable {
require(false, "Withdrawals are disabled");
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
nonce: messageNonce(),
sender: msg.sender,
target: _target,
value: msg.value,
gasLimit: _gasLimit,
data: _data
})
);
sentMessages[withdrawalHash] = true;
emit MessagePassed(messageNonce(), msg.sender, _target, msg.value, _gasLimit, _data, withdrawalHash);
unchecked {
++msgNonce;
}
}
/// @notice Retrieves the next message nonce. Message version will be added to the upper two
/// bytes of the message nonce. Message version allows us to treat messages as having
/// different structures.
/// @return Nonce of the next message to be sent, with added message version.
function messageNonce() public view returns (uint256) {
return Encoding.encodeVersionedNonce(msgNonce, MESSAGE_VERSION);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/// @title Burn
/// @notice Utilities for burning stuff.
library Burn {
/// @notice Burns a given amount of ETH.
/// @param _amount Amount of ETH to burn.
function eth(uint256 _amount) internal {
new Burner{ value: _amount }();
}
/// @notice Burns a given amount of gas.
/// @param _amount Amount of gas to burn.
function gas(uint256 _amount) internal view {
uint256 i = 0;
uint256 initialGas = gasleft();
while (initialGas - gasleft() < _amount) {
++i;
}
}
}
/// @title Burner
/// @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to
/// the contract from the circulating supply. Self-destructing is the only way to remove ETH
/// from the circulating supply.
contract Burner {
constructor() payable {
selfdestruct(payable(address(this)));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Types } from "src/libraries/Types.sol";
import { Hashing } from "src/libraries/Hashing.sol";
import { RLPWriter } from "src/libraries/rlp/RLPWriter.sol";
/// @title Encoding
/// @notice Encoding handles Optimism's various different encoding schemes.
library Encoding {
/// @notice RLP encodes the L2 transaction that would be generated when a given deposit is sent
/// to the L2 system. Useful for searching for a deposit in the L2 system. The
/// transaction is prefixed with 0x7e to identify its EIP-2718 type.
/// @param _tx User deposit transaction to encode.
/// @return RLP encoded L2 deposit transaction.
function encodeDepositTransaction(Types.UserDepositTransaction memory _tx) internal pure returns (bytes memory) {
bytes32 source = Hashing.hashDepositSource(_tx.l1BlockHash, _tx.logIndex);
bytes[] memory raw = new bytes[](8);
raw[0] = RLPWriter.writeBytes(abi.encodePacked(source));
raw[1] = RLPWriter.writeAddress(_tx.from);
raw[2] = _tx.isCreation ? RLPWriter.writeBytes("") : RLPWriter.writeAddress(_tx.to);
raw[3] = RLPWriter.writeUint(_tx.mint);
raw[4] = RLPWriter.writeUint(_tx.value);
raw[5] = RLPWriter.writeUint(uint256(_tx.gasLimit));
raw[6] = RLPWriter.writeBool(false);
raw[7] = RLPWriter.writeBytes(_tx.data);
return abi.encodePacked(uint8(0x7e), RLPWriter.writeList(raw));
}
/// @notice Encodes the cross domain message based on the version that is encoded into the
/// message nonce.
/// @param _nonce Message nonce with version encoded into the first two bytes.
/// @param _sender Address of the sender of the message.
/// @param _target Address of the target of the message.
/// @param _value ETH value to send to the target.
/// @param _gasLimit Gas limit to use for the message.
/// @param _data Data to send with the message.
/// @return Encoded cross domain message.
function encodeCrossDomainMessage(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
)
internal
pure
returns (bytes memory)
{
(, uint16 version) = decodeVersionedNonce(_nonce);
if (version == 0) {
return encodeCrossDomainMessageV0(_target, _sender, _data, _nonce);
} else if (version == 1) {
return encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);
} else {
revert("Encoding: unknown cross domain message version");
}
}
/// @notice Encodes a cross domain message based on the V0 (legacy) encoding.
/// @param _target Address of the target of the message.
/// @param _sender Address of the sender of the message.
/// @param _data Data to send with the message.
/// @param _nonce Message nonce.
/// @return Encoded cross domain message.
function encodeCrossDomainMessageV0(
address _target,
address _sender,
bytes memory _data,
uint256 _nonce
)
internal
pure
returns (bytes memory)
{
// nosemgrep: sol-style-use-abi-encodecall
return abi.encodeWithSignature("relayMessage(address,address,bytes,uint256)", _target, _sender, _data, _nonce);
}
/// @notice Encodes a cross domain message based on the V1 (current) encoding.
/// @param _nonce Message nonce.
/// @param _sender Address of the sender of the message.
/// @param _target Address of the target of the message.
/// @param _value ETH value to send to the target.
/// @param _gasLimit Gas limit to use for the message.
/// @param _data Data to send with the message.
/// @return Encoded cross domain message.
function encodeCrossDomainMessageV1(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
)
internal
pure
returns (bytes memory)
{
// nosemgrep: sol-style-use-abi-encodecall
return abi.encodeWithSignature(
"relayMessage(uint256,address,address,uint256,uint256,bytes)",
_nonce,
_sender,
_target,
_value,
_gasLimit,
_data
);
}
/// @notice Adds a version number into the first two bytes of a message nonce.
/// @param _nonce Message nonce to encode into.
/// @param _version Version number to encode into the message nonce.
/// @return Message nonce with version encoded into the first two bytes.
function encodeVersionedNonce(uint240 _nonce, uint16 _version) internal pure returns (uint256) {
uint256 nonce;
assembly {
nonce := or(shl(240, _version), _nonce)
}
return nonce;
}
/// @notice Pulls the version out of a version-encoded nonce.
/// @param _nonce Message nonce with version encoded into the first two bytes.
/// @return Nonce without encoded version.
/// @return Version of the message.
function decodeVersionedNonce(uint256 _nonce) internal pure returns (uint240, uint16) {
uint240 nonce;
uint16 version;
assembly {
nonce := and(_nonce, 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
version := shr(240, _nonce)
}
return (nonce, version);
}
/// @notice Returns an appropriately encoded call to L1Block.setL1BlockValuesEcotone
/// @param _baseFeeScalar L1 base fee Scalar
/// @param _blobBaseFeeScalar L1 blob base fee Scalar
/// @param _sequenceNumber Number of L2 blocks since epoch start.
/// @param _timestamp L1 timestamp.
/// @param _number L1 blocknumber.
/// @param _baseFee L1 base fee.
/// @param _blobBaseFee L1 blob base fee.
/// @param _hash L1 blockhash.
/// @param _batcherHash Versioned hash to authenticate batcher by.
function encodeSetL1BlockValuesEcotone(
uint32 _baseFeeScalar,
uint32 _blobBaseFeeScalar,
uint64 _sequenceNumber,
uint64 _timestamp,
uint64 _number,
uint256 _baseFee,
uint256 _blobBaseFee,
bytes32 _hash,
bytes32 _batcherHash
)
internal
pure
returns (bytes memory)
{
bytes4 functionSignature = bytes4(keccak256("setL1BlockValuesEcotone()"));
return abi.encodePacked(
functionSignature,
_baseFeeScalar,
_blobBaseFeeScalar,
_sequenceNumber,
_timestamp,
_number,
_baseFee,
_blobBaseFee,
_hash,
_batcherHash
);
}
/// @notice Returns an appropriately encoded call to L1Block.setL1BlockValuesInterop
/// @param _baseFeeScalar L1 base fee Scalar
/// @param _blobBaseFeeScalar L1 blob base fee Scalar
/// @param _sequenceNumber Number of L2 blocks since epoch start.
/// @param _timestamp L1 timestamp.
/// @param _number L1 blocknumber.
/// @param _baseFee L1 base fee.
/// @param _blobBaseFee L1 blob base fee.
/// @param _hash L1 blockhash.
/// @param _batcherHash Versioned hash to authenticate batcher by.
function encodeSetL1BlockValuesInterop(
uint32 _baseFeeScalar,
uint32 _blobBaseFeeScalar,
uint64 _sequenceNumber,
uint64 _timestamp,
uint64 _number,
uint256 _baseFee,
uint256 _blobBaseFee,
bytes32 _hash,
bytes32 _batcherHash
)
internal
pure
returns (bytes memory)
{
bytes4 functionSignature = bytes4(keccak256("setL1BlockValuesInterop()"));
return abi.encodePacked(
functionSignature,
_baseFeeScalar,
_blobBaseFeeScalar,
_sequenceNumber,
_timestamp,
_number,
_baseFee,
_blobBaseFee,
_hash,
_batcherHash
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Types } from "src/libraries/Types.sol";
import { Encoding } from "src/libraries/Encoding.sol";
/// @title Hashing
/// @notice Hashing handles Optimism's various different hashing schemes.
library Hashing {
/// @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a
/// given deposit is sent to the L2 system. Useful for searching for a deposit in the L2
/// system.
/// @param _tx User deposit transaction to hash.
/// @return Hash of the RLP encoded L2 deposit transaction.
function hashDepositTransaction(Types.UserDepositTransaction memory _tx) internal pure returns (bytes32) {
return keccak256(Encoding.encodeDepositTransaction(_tx));
}
/// @notice Computes the deposit transaction's "source hash", a value that guarantees the hash
/// of the L2 transaction that corresponds to a deposit is unique and is
/// deterministically generated from L1 transaction data.
/// @param _l1BlockHash Hash of the L1 block where the deposit was included.
/// @param _logIndex The index of the log that created the deposit transaction.
/// @return Hash of the deposit transaction's "source hash".
function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex) internal pure returns (bytes32) {
bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex));
return keccak256(abi.encode(bytes32(0), depositId));
}
/// @notice Hashes the cross domain message based on the version that is encoded into the
/// message nonce.
/// @param _nonce Message nonce with version encoded into the first two bytes.
/// @param _sender Address of the sender of the message.
/// @param _target Address of the target of the message.
/// @param _value ETH value to send to the target.
/// @param _gasLimit Gas limit to use for the message.
/// @param _data Data to send with the message.
/// @return Hashed cross domain message.
function hashCrossDomainMessage(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
)
internal
pure
returns (bytes32)
{
(, uint16 version) = Encoding.decodeVersionedNonce(_nonce);
if (version == 0) {
return hashCrossDomainMessageV0(_target, _sender, _data, _nonce);
} else if (version == 1) {
return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data);
} else {
revert("Hashing: unknown cross domain message version");
}
}
/// @notice Hashes a cross domain message based on the V0 (legacy) encoding.
/// @param _target Address of the target of the message.
/// @param _sender Address of the sender of the message.
/// @param _data Data to send with the message.
/// @param _nonce Message nonce.
/// @return Hashed cross domain message.
function hashCrossDomainMessageV0(
address _target,
address _sender,
bytes memory _data,
uint256 _nonce
)
internal
pure
returns (bytes32)
{
return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce));
}
/// @notice Hashes a cross domain message based on the V1 (current) encoding.
/// @param _nonce Message nonce.
/// @param _sender Address of the sender of the message.
/// @param _target Address of the target of the message.
/// @param _value ETH value to send to the target.
/// @param _gasLimit Gas limit to use for the message.
/// @param _data Data to send with the message.
/// @return Hashed cross domain message.
function hashCrossDomainMessageV1(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
bytes memory _data
)
internal
pure
returns (bytes32)
{
return keccak256(Encoding.encodeCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data));
}
/// @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract
/// @param _tx Withdrawal transaction to hash.
/// @return Hashed withdrawal transaction.
function hashWithdrawal(Types.WithdrawalTransaction memory _tx) internal pure returns (bytes32) {
return keccak256(abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data));
}
/// @notice Hashes the various elements of an output root proof into an output root hash which
/// can be used to check if the proof is valid.
/// @param _outputRootProof Output root proof which should hash to an output root.
/// @return Hashed output root proof.
function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof) internal pure returns (bytes32) {
return keccak256(
abi.encode(
_outputRootProof.version,
_outputRootProof.stateRoot,
_outputRootProof.messagePasserStorageRoot,
_outputRootProof.latestBlockhash
)
);
}
/// @notice Generates a unique hash for cross l2 messages. This hash is used to identify
/// the message and ensure it is not relayed more than once.
/// @param _destination Chain ID of the destination chain.
/// @param _source Chain ID of the source chain.
/// @param _nonce Unique nonce associated with the message to prevent replay attacks.
/// @param _sender Address of the user who originally sent the message.
/// @param _target Address of the contract or wallet that the message is targeting on the destination chain.
/// @param _message The message payload to be relayed to the target on the destination chain.
/// @return Hash of the encoded message parameters, used to uniquely identify the message.
function hashL2toL2CrossDomainMessage(
uint256 _destination,
uint256 _source,
uint256 _nonce,
address _sender,
address _target,
bytes memory _message
)
internal
pure
returns (bytes32)
{
return keccak256(abi.encode(_destination, _source, _nonce, _sender, _target, _message));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Types
/// @notice Contains various types used throughout the Optimism contract system.
library Types {
/// @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1
/// timestamp that the output root is posted. This timestamp is used to verify that the
/// finalization period has passed since the output root was submitted.
/// @custom:field outputRoot Hash of the L2 output.
/// @custom:field timestamp Timestamp of the L1 block that the output root was submitted in.
/// @custom:field l2BlockNumber L2 block number that the output corresponds to.
struct OutputProposal {
bytes32 outputRoot;
uint128 timestamp;
uint128 l2BlockNumber;
}
/// @notice Struct representing the elements that are hashed together to generate an output root
/// which itself represents a snapshot of the L2 state.
/// @custom:field version Version of the output root.
/// @custom:field stateRoot Root of the state trie at the block of this output.
/// @custom:field messagePasserStorageRoot Root of the message passer storage trie.
/// @custom:field latestBlockhash Hash of the block this output was generated from.
struct OutputRootProof {
bytes32 version;
bytes32 stateRoot;
bytes32 messagePasserStorageRoot;
bytes32 latestBlockhash;
}
/// @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end
/// user (as opposed to a system deposit transaction generated by the system).
/// @custom:field from Address of the sender of the transaction.
/// @custom:field to Address of the recipient of the transaction.
/// @custom:field isCreation True if the transaction is a contract creation.
/// @custom:field value Value to send to the recipient.
/// @custom:field mint Amount of ETH to mint.
/// @custom:field gasLimit Gas limit of the transaction.
/// @custom:field data Data of the transaction.
/// @custom:field l1BlockHash Hash of the block the transaction was submitted in.
/// @custom:field logIndex Index of the log in the block the transaction was submitted in.
struct UserDepositTransaction {
address from;
address to;
bool isCreation;
uint256 value;
uint256 mint;
uint64 gasLimit;
bytes data;
bytes32 l1BlockHash;
uint256 logIndex;
}
/// @notice Struct representing a withdrawal transaction.
/// @custom:field nonce Nonce of the withdrawal transaction
/// @custom:field sender Address of the sender of the transaction.
/// @custom:field target Address of the recipient of the transaction.
/// @custom:field value Value to send to the recipient.
/// @custom:field gasLimit Gas limit of the transaction.
/// @custom:field data Data of the transaction.
struct WithdrawalTransaction {
uint256 nonce;
address sender;
address target;
uint256 value;
uint256 gasLimit;
bytes data;
}
/// @notice Enum representing where the FeeVault withdraws funds to.
/// @custom:value L1 FeeVault withdraws funds to L1.
/// @custom:value L2 FeeVault withdraws funds to L2.
enum WithdrawalNetwork {
L1,
L2
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @custom:attribution https://github.com/bakaoh/solidity-rlp-encode
/// @title RLPWriter
/// @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's
/// RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor
/// modifications to improve legibility.
library RLPWriter {
/// @notice RLP encodes a byte string.
/// @param _in The byte string to encode.
/// @return out_ The RLP encoded string in bytes.
function writeBytes(bytes memory _in) internal pure returns (bytes memory out_) {
if (_in.length == 1 && uint8(_in[0]) < 128) {
out_ = _in;
} else {
out_ = abi.encodePacked(_writeLength(_in.length, 128), _in);
}
}
/// @notice RLP encodes a list of RLP encoded byte byte strings.
/// @param _in The list of RLP encoded byte strings.
/// @return list_ The RLP encoded list of items in bytes.
function writeList(bytes[] memory _in) internal pure returns (bytes memory list_) {
list_ = _flatten(_in);
list_ = abi.encodePacked(_writeLength(list_.length, 192), list_);
}
/// @notice RLP encodes a string.
/// @param _in The string to encode.
/// @return out_ The RLP encoded string in bytes.
function writeString(string memory _in) internal pure returns (bytes memory out_) {
out_ = writeBytes(bytes(_in));
}
/// @notice RLP encodes an address.
/// @param _in The address to encode.
/// @return out_ The RLP encoded address in bytes.
function writeAddress(address _in) internal pure returns (bytes memory out_) {
out_ = writeBytes(abi.encodePacked(_in));
}
/// @notice RLP encodes a uint.
/// @param _in The uint256 to encode.
/// @return out_ The RLP encoded uint256 in bytes.
function writeUint(uint256 _in) internal pure returns (bytes memory out_) {
out_ = writeBytes(_toBinary(_in));
}
/// @notice RLP encodes a bool.
/// @param _in The bool to encode.
/// @return out_ The RLP encoded bool in bytes.
function writeBool(bool _in) internal pure returns (bytes memory out_) {
out_ = new bytes(1);
out_[0] = (_in ? bytes1(0x01) : bytes1(0x80));
}
/// @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.
/// @param _len The length of the string or the payload.
/// @param _offset 128 if item is string, 192 if item is list.
/// @return out_ RLP encoded bytes.
function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory out_) {
if (_len < 56) {
out_ = new bytes(1);
out_[0] = bytes1(uint8(_len) + uint8(_offset));
} else {
uint256 lenLen;
uint256 i = 1;
while (_len / i != 0) {
lenLen++;
i *= 256;
}
out_ = new bytes(lenLen + 1);
out_[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);
for (i = 1; i <= lenLen; i++) {
out_[i] = bytes1(uint8((_len / (256 ** (lenLen - i))) % 256));
}
}
}
/// @notice Encode integer in big endian binary form with no leading zeroes.
/// @param _x The integer to encode.
/// @return out_ RLP encoded bytes.
function _toBinary(uint256 _x) private pure returns (bytes memory out_) {
bytes memory b = abi.encodePacked(_x);
uint256 i = 0;
for (; i < 32; i++) {
if (b[i] != 0) {
break;
}
}
out_ = new bytes(32 - i);
for (uint256 j = 0; j < out_.length; j++) {
out_[j] = b[i++];
}
}
/// @custom:attribution https://github.com/Arachnid/solidity-stringutils
/// @notice Copies a piece of memory to another location.
/// @param _dest Destination location.
/// @param _src Source location.
/// @param _len Length of memory to copy.
function _memcpy(uint256 _dest, uint256 _src, uint256 _len) private pure {
uint256 dest = _dest;
uint256 src = _src;
uint256 len = _len;
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
uint256 mask;
unchecked {
mask = 256 ** (32 - len) - 1;
}
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
/// @custom:attribution https://github.com/sammayo/solidity-rlp-encoder
/// @notice Flattens a list of byte strings into one byte string.
/// @param _list List of byte strings to flatten.
/// @return out_ The flattened byte string.
function _flatten(bytes[] memory _list) private pure returns (bytes memory out_) {
if (_list.length == 0) {
return new bytes(0);
}
uint256 len;
uint256 i = 0;
for (; i < _list.length; i++) {
len += _list[i].length;
}
out_ = new bytes(len);
uint256 flattenedPtr;
assembly {
flattenedPtr := add(out_, 0x20)
}
for (i = 0; i < _list.length; i++) {
bytes memory item = _list[i];
uint256 listPtr;
assembly {
listPtr := add(item, 0x20)
}
_memcpy(flattenedPtr, listPtr, item.length);
flattenedPtr += _list[i].length;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title ISemver
/// @notice ISemver is a simple contract for ensuring that contracts are
/// versioned using semantic versioning.
interface ISemver {
/// @notice Getter for the semantic version of the contract. This is not
/// meant to be used onchain but instead meant to be used by offchain
/// tooling.
/// @return Semver contract version as a string.
function version() external view returns (string memory);
}{
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "none",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 999999
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-v5/=lib/openzeppelin-contracts-v5/contracts/",
"@rari-capital/solmate/=lib/solmate/",
"@lib-keccak/=lib/lib-keccak/contracts/lib/",
"@solady/=lib/solady/src/",
"@solady-v0.0.245/=lib/solady-v0.0.245/src/",
"forge-std/=lib/forge-std/src/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"safe-contracts/=lib/safe-contracts/contracts/",
"kontrol-cheatcodes/=lib/kontrol-cheatcodes/src/",
"gelato/=lib/automate/contracts/",
"@solady-test/=lib/lib-keccak/lib/solady/test/",
"automate/=lib/automate/contracts/",
"erc4626-tests/=lib/openzeppelin-contracts-v5/lib/erc4626-tests/",
"hardhat/=lib/automate/node_modules/hardhat/",
"lib-keccak/=lib/lib-keccak/contracts/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts-v5/=lib/openzeppelin-contracts-v5/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"prb-test/=lib/automate/lib/prb-test/src/",
"prb/-est/=lib/automate/lib/prb-test/src/",
"solady-v0.0.245/=lib/solady-v0.0.245/src/",
"solady/=lib/solady/",
"solmate/=lib/solmate/src/"
],
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasLimit","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"withdrawalHash","type":"bytes32"}],"name":"MessagePassed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawerBalanceBurnt","type":"event"},{"inputs":[],"name":"MESSAGE_VERSION","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"initiateWithdrawal","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"messageNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"sentMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405234801561001057600080fd5b506104a1806100206000396000f3fe6080604052600436106100695760003560e01c806382e3702d1161004357806382e3702d1461012a578063c2b3e5ac1461016a578063ecc704281461017d57600080fd5b80633f827a5a1461009257806344df8e70146100bf57806354fd4d50146100d457600080fd5b3661008d5761008b33620186a0604051806020016040528060008152506101e2565b005b600080fd5b34801561009e57600080fd5b506100a7600181565b60405161ffff90911681526020015b60405180910390f35b3480156100cb57600080fd5b5061008b610248565b3480156100e057600080fd5b5061011d6040518060400160405280600c81526020017f312e312e312d626574612e31000000000000000000000000000000000000000081525081565b6040516100b69190610326565b34801561013657600080fd5b5061015a610145366004610340565b60006020819052908152604090205460ff1681565b60405190151581526020016100b6565b61008b610178366004610388565b6101e2565b34801561018957600080fd5b506101d46001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016100b6565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f5769746864726177616c73206172652064697361626c65640000000000000000604482015260640160405180910390fd5b4761025281610280565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b8060405161028d906102af565b6040518091039082f09050801580156102aa573d6000803e3d6000fd5b505050565b60088061048d83390190565b6000815180845260005b818110156102e1576020818501810151868301820152016102c5565b818111156102f3576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061033960208301846102bb565b9392505050565b60006020828403121561035257600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060006060848603121561039d57600080fd5b833573ffffffffffffffffffffffffffffffffffffffff811681146103c157600080fd5b925060208401359150604084013567ffffffffffffffff808211156103e557600080fd5b818601915086601f8301126103f957600080fd5b81358181111561040b5761040b610359565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561045157610451610359565b8160405282815289602084870101111561046a57600080fd5b826020860160208301376000602084830101528095505050505050925092509256fe608060405230fffea164736f6c634300080f000a
Deployed Bytecode
0x6080604052600436106100695760003560e01c806382e3702d1161004357806382e3702d1461012a578063c2b3e5ac1461016a578063ecc704281461017d57600080fd5b80633f827a5a1461009257806344df8e70146100bf57806354fd4d50146100d457600080fd5b3661008d5761008b33620186a0604051806020016040528060008152506101e2565b005b600080fd5b34801561009e57600080fd5b506100a7600181565b60405161ffff90911681526020015b60405180910390f35b3480156100cb57600080fd5b5061008b610248565b3480156100e057600080fd5b5061011d6040518060400160405280600c81526020017f312e312e312d626574612e31000000000000000000000000000000000000000081525081565b6040516100b69190610326565b34801561013657600080fd5b5061015a610145366004610340565b60006020819052908152604090205460ff1681565b60405190151581526020016100b6565b61008b610178366004610388565b6101e2565b34801561018957600080fd5b506101d46001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016100b6565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f5769746864726177616c73206172652064697361626c65640000000000000000604482015260640160405180910390fd5b4761025281610280565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b8060405161028d906102af565b6040518091039082f09050801580156102aa573d6000803e3d6000fd5b505050565b60088061048d83390190565b6000815180845260005b818110156102e1576020818501810151868301820152016102c5565b818111156102f3576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061033960208301846102bb565b9392505050565b60006020828403121561035257600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060006060848603121561039d57600080fd5b833573ffffffffffffffffffffffffffffffffffffffff811681146103c157600080fd5b925060208401359150604084013567ffffffffffffffff808211156103e557600080fd5b818601915086601f8301126103f957600080fd5b81358181111561040b5761040b610359565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561045157610451610359565b8160405282815289602084870101111561046a57600080fd5b826020860160208301376000602084830101528095505050505050925092509256fe608060405230fffea164736f6c634300080f000a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.