Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/BridgeController.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// Import necessary interfaces and contracts
import { AddressCast } from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol";
import {
MessagingFee,
MessagingReceipt
} from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { Origin } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
import { OAppOptionsType3 } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol";
import { ReadCodecV1, EVMCallRequestV1 } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/ReadCodecV1.sol";
import { OAppRead } from "@layerzerolabs/oapp-evm/contracts/oapp/OAppRead.sol";
import { OAppCore } from "@layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IBridge } from "./interfaces/IBridge.sol";
import { IController } from "./interfaces/IController.sol";
import { IMessageLibManager } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol";
import { SetConfigParam } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol";
/**
* @title BridgeController
* @notice Manages the bridge to enable a immutable peering on LayerZero, while allowing for potential expansion of the
* bridge to other chains.
*/
contract BridgeController is IController, OAppRead, OAppOptionsType3 {
uint32 public constant DEFAULT_GAS_LIMIT = 200_000;
uint32 private constant READ_TIME_DELAY = 6 minutes;
uint32 private constant TIMEOUT_OFFSET = 10 minutes;
uint8 public constant MAX_RETRY_PEER = 3;
uint16 public constant READ_TYPE = 1;
address public immutable BRIDGE_ADDRESS;
/// @notice LayerZero read channel ID.
uint32 public READ_CHANNEL;
mapping(uint64 chainId => PeerStatus) internal peerStatusList;
mapping(uint32 lzEID => uint64 chainId) public layerZeroToChainId;
mapping(bytes32 guid => uint32 chainId) public messageToTargetChainId;
constructor(address _endpoint, address _owner, address _bridgeAddress, uint32 _readChannel)
OAppRead(_endpoint, _owner)
Ownable(_owner)
{
READ_CHANNEL = _readChannel;
BRIDGE_ADDRESS = _bridgeAddress;
_setPeer(_readChannel, AddressCast.toBytes32(address(this)));
}
function setBridgePeer(
uint64 _targetChainId,
uint32 _eid,
bytes32 _peer,
address _libReceiver,
address _libSender,
SetConfigParam[] calldata _configRead,
SetConfigParam[] calldata _configWrite
) external onlyOwner {
PeerStatus storage status = peerStatusList[_targetChainId];
if (status.requestTimeout != 0) {
require(!status.succeed, PeerAlreadyExists());
require(status.requestTimeout <= block.timestamp, PeerAlreadyExists());
require(status.failures >= MAX_RETRY_PEER, PeerAlreadyExists());
}
peerStatusList[_targetChainId] = PeerStatus(_targetChainId, _eid, _peer, 1, 0, false);
status = peerStatusList[_targetChainId];
layerZeroToChainId[_eid] = _targetChainId;
OAppCore(BRIDGE_ADDRESS).setPeer(_eid, _peer);
IMessageLibManager(endpoint).setConfig(BRIDGE_ADDRESS, _libReceiver, _configRead);
IMessageLibManager(endpoint).setConfig(BRIDGE_ADDRESS, _libSender, _configRead);
IMessageLibManager(endpoint).setConfig(BRIDGE_ADDRESS, _libSender, _configWrite);
}
function validatePeer(uint32 _targetChainId, uint32 _gasLimit, bytes calldata _extraOptions)
external
payable
onlyOwner
{
PeerStatus storage status = peerStatusList[_targetChainId];
require(status.requestTimeout == 1, "Validation already sent");
(uint256 callingFee, uint256 readingFee) = getLzFees(_targetChainId, _gasLimit, _extraOptions);
require(msg.value == callingFee + readingFee, "Not enough native fee");
IBridge(BRIDGE_ADDRESS).sendMessageAsController{ value: callingFee }(status.lzEndpointId, _gasLimit, msg.sender);
MessagingReceipt memory receipt = this.readBridgeConnection{ value: readingFee }(
_peerToAddress(status.peer), status.lzEndpointId, READ_TIME_DELAY, _extraOptions
);
messageToTargetChainId[receipt.guid] = _targetChainId;
status.requestTimeout = uint32(block.timestamp + READ_TIME_DELAY + TIMEOUT_OFFSET);
}
function retryBridgePeering(uint32 _targetChainId, uint32 _gasLimit, bytes calldata _extraOptions) external payable {
PeerStatus storage status = peerStatusList[_targetChainId];
require(status.lzEndpointId != 0, "Peer not set");
require(!status.succeed, "Peer already succeed");
require(status.requestTimeout < block.timestamp, "Request still ongoing");
require(status.failures < MAX_RETRY_PEER, "Max retry reached");
status.failures++;
status.requestTimeout = uint32(block.timestamp + TIMEOUT_OFFSET);
(, uint256 readingFee) = getLzFees(_targetChainId, _gasLimit, _extraOptions);
require(msg.value == readingFee, "Not enough native fee");
MessagingReceipt memory receipt =
this.readBridgeConnection{ value: readingFee }(_peerToAddress(status.peer), status.lzEndpointId, 0, _extraOptions);
messageToTargetChainId[receipt.guid] = _targetChainId;
}
function getLzFees(uint64 _chainId, uint32 _gasLimit, bytes calldata _extraOptions)
public
view
returns (uint256 calling_, uint256 reading_)
{
PeerStatus memory status = peerStatusList[_chainId];
calling_ =
IBridge(BRIDGE_ADDRESS).estimateFee(status.lzEndpointId, 0, _gasLimit == 0 ? DEFAULT_GAS_LIMIT : _gasLimit);
reading_ = quoteReadFee(_peerToAddress(status.peer), status.lzEndpointId, _extraOptions).nativeFee;
return (calling_, reading_);
}
function _peerToAddress(bytes32 _peer) private pure returns (address) {
return address(uint160(uint256(_peer)));
}
function quoteReadFee(address _targetContractAddress, uint32 _targetEid, bytes calldata _extraOptions)
public
view
returns (MessagingFee memory fee)
{
return _quote(
READ_CHANNEL,
_getCmd(_targetContractAddress, _targetEid, 0),
combineOptions(READ_CHANNEL, READ_TYPE, _extraOptions),
false
);
}
function readBridgeConnection(
address _targetContractAddress,
uint32 _targetEid,
uint64 _readDelay,
bytes calldata _extraOptions
) external payable returns (MessagingReceipt memory) {
require(msg.sender == address(this), "Only callable by BridgeController");
bytes memory cmd = _getCmd(_targetContractAddress, _targetEid, _readDelay);
return _lzSend(
READ_CHANNEL,
cmd,
combineOptions(READ_CHANNEL, READ_TYPE, _extraOptions),
MessagingFee(msg.value, 0),
payable(msg.sender)
);
}
function _getCmd(address _targetContractAddress, uint32 _targetEid, uint64 _readDelay)
internal
view
returns (bytes memory)
{
bytes memory callData = abi.encodeWithSelector(IBridge.isChainLinked.selector, uint64(block.chainid));
EVMCallRequestV1[] memory readRequests = new EVMCallRequestV1[](1);
readRequests[0] = EVMCallRequestV1({
appRequestLabel: 1, // Label for tracking this specific request
targetEid: _targetEid, // WHICH chain to read from
isBlockNum: false, // Use timestamp (not block number)
blockNumOrTimestamp: uint64(block.timestamp + _readDelay), // WHEN to read the state (current time)
confirmations: 15, // HOW many confirmations to wait for
to: _targetContractAddress, // WHERE - the contract address to call
callData: callData // WHAT - the function call to execute
});
return ReadCodecV1.encode(0, readRequests);
}
function _lzReceive(
Origin calldata, /*_origin*/
bytes32 _guid,
bytes calldata _message,
address, /*_executor*/
bytes calldata /*_extraData*/
) internal override {
bool linked = abi.decode(_message, (bool));
if (!linked) return;
_completeLink(messageToTargetChainId[_guid]);
}
function _completeLink(uint64 _chainId) internal {
PeerStatus storage status = peerStatusList[_chainId];
if (status.peer == bytes32(0)) {
return;
}
status.succeed = true;
emit PeerLinkingCompleted(_chainId);
}
function setReadChannel(uint32 _channelId, bool _active) public override onlyOwner {
_setPeer(_channelId, _active ? AddressCast.toBytes32(address(this)) : bytes32(0));
READ_CHANNEL = _channelId;
}
function getPeerStatus(uint64 _chainId) external view returns (PeerStatus memory) {
return peerStatusList[_chainId];
}
function IsValidDestination(uint32 _dstEid) external view override returns (bool) {
return peerStatusList[layerZeroToChainId[_dstEid]].succeed;
}
receive() external payable {
revert("Blocked Direct Native Payment");
}
}
"
},
"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol": {
"content": "// SPDX-License-Identifier: LZBL-1.2
pragma solidity ^0.8.20;
library AddressCast {
error AddressCast_InvalidSizeForAddress();
error AddressCast_InvalidAddress();
function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) {
if (_addressBytes.length > 32) revert AddressCast_InvalidAddress();
result = bytes32(_addressBytes);
unchecked {
uint256 offset = 32 - _addressBytes.length;
result = result >> (offset * 8);
}
}
function toBytes32(address _address) internal pure returns (bytes32 result) {
result = bytes32(uint256(uint160(_address)));
}
function toBytes(bytes32 _addressBytes32, uint256 _size) internal pure returns (bytes memory result) {
if (_size == 0 || _size > 32) revert AddressCast_InvalidSizeForAddress();
result = new bytes(_size);
unchecked {
uint256 offset = 256 - _size * 8;
assembly {
mstore(add(result, 32), shl(offset, _addressBytes32))
}
}
}
function toAddress(bytes32 _addressBytes32) internal pure returns (address result) {
result = address(uint160(uint256(_addressBytes32)));
}
function toAddress(bytes calldata _addressBytes) internal pure returns (address result) {
if (_addressBytes.length != 20) revert AddressCast_InvalidAddress();
result = address(bytes20(_addressBytes));
}
}
"
},
"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { IMessageLibManager } from "./IMessageLibManager.sol";
import { IMessagingComposer } from "./IMessagingComposer.sol";
import { IMessagingChannel } from "./IMessagingChannel.sol";
import { IMessagingContext } from "./IMessagingContext.sol";
struct MessagingParams {
uint32 dstEid;
bytes32 receiver;
bytes message;
bytes options;
bool payInLzToken;
}
struct MessagingReceipt {
bytes32 guid;
uint64 nonce;
MessagingFee fee;
}
struct MessagingFee {
uint256 nativeFee;
uint256 lzTokenFee;
}
struct Origin {
uint32 srcEid;
bytes32 sender;
uint64 nonce;
}
interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {
event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);
event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);
event PacketDelivered(Origin origin, address receiver);
event LzReceiveAlert(
address indexed receiver,
address indexed executor,
Origin origin,
bytes32 guid,
uint256 gas,
uint256 value,
bytes message,
bytes extraData,
bytes reason
);
event LzTokenSet(address token);
event DelegateSet(address sender, address delegate);
function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);
function send(
MessagingParams calldata _params,
address _refundAddress
) external payable returns (MessagingReceipt memory);
function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;
function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);
function initializable(Origin calldata _origin, address _receiver) external view returns (bool);
function lzReceive(
Origin calldata _origin,
address _receiver,
bytes32 _guid,
bytes calldata _message,
bytes calldata _extraData
) external payable;
// oapp can burn messages partially by calling this function with its own business logic if messages are verified in order
function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;
function setLzToken(address _lzToken) external;
function lzToken() external view returns (address);
function nativeToken() external view returns (address);
function setDelegate(address _delegate) external;
}
"
},
"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppSender, MessagingFee, MessagingReceipt } from "./OAppSender.sol";
// @dev Import the 'Origin' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppReceiver, Origin } from "./OAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OApp
* @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.
*/
abstract contract OApp is OAppSender, OAppReceiver {
/**
* @dev Constructor to initialize the OApp with the provided endpoint and owner.
* @param _endpoint The address of the LOCAL LayerZero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {}
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol implementation.
* @return receiverVersion The version of the OAppReceiver.sol implementation.
*/
function oAppVersion()
public
pure
virtual
override(OAppSender, OAppReceiver)
returns (uint64 senderVersion, uint64 receiverVersion)
{
return (SENDER_VERSION, RECEIVER_VERSION);
}
}
"
},
"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppOptionsType3, EnforcedOptionParam } from "../interfaces/IOAppOptionsType3.sol";
/**
* @title OAppOptionsType3
* @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options.
*/
abstract contract OAppOptionsType3 is IOAppOptionsType3, Ownable {
uint16 internal constant OPTION_TYPE_3 = 3;
// @dev The "msgType" should be defined in the child contract.
mapping(uint32 eid => mapping(uint16 msgType => bytes enforcedOption)) public enforcedOptions;
/**
* @dev Sets the enforced options for specific endpoint and message type combinations.
* @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
* @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
* eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
* if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
*/
function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner {
_setEnforcedOptions(_enforcedOptions);
}
/**
* @dev Sets the enforced options for specific endpoint and message type combinations.
* @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
*
* @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
* @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
* eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
* if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
*/
function _setEnforcedOptions(EnforcedOptionParam[] memory _enforcedOptions) internal virtual {
for (uint256 i = 0; i < _enforcedOptions.length; i++) {
// @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining.
_assertOptionsType3(_enforcedOptions[i].options);
enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options;
}
emit EnforcedOptionSet(_enforcedOptions);
}
/**
* @notice Combines options for a given endpoint and message type.
* @param _eid The endpoint ID.
* @param _msgType The OAPP message type.
* @param _extraOptions Additional options passed by the caller.
* @return options The combination of caller specified options AND enforced options.
*
* @dev If there is an enforced lzReceive option:
* - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether}
* - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function.
* @dev This presence of duplicated options is handled off-chain in the verifier/executor.
*/
function combineOptions(
uint32 _eid,
uint16 _msgType,
bytes calldata _extraOptions
) public view virtual returns (bytes memory) {
bytes memory enforced = enforcedOptions[_eid][_msgType];
// No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options.
if (enforced.length == 0) return _extraOptions;
// No caller options, return enforced
if (_extraOptions.length == 0) return enforced;
// @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined.
if (_extraOptions.length >= 2) {
_assertOptionsType3(_extraOptions);
// @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced.
return bytes.concat(enforced, _extraOptions[2:]);
}
// No valid set of options was found.
revert InvalidOptions(_extraOptions);
}
/**
* @dev Internal function to assert that options are of type 3.
* @param _options The options to be checked.
*/
function _assertOptionsType3(bytes memory _options) internal pure virtual {
uint16 optionsType;
assembly {
optionsType := mload(add(_options, 2))
}
if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);
}
}
"
},
"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/libs/ReadCodecV1.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol";
struct EVMCallRequestV1 {
uint16 appRequestLabel; // Label identifying the application or type of request (can be use in lzCompute)
uint32 targetEid; // Target endpoint ID (representing a target blockchain)
bool isBlockNum; // True if the request = block number, false if timestamp
uint64 blockNumOrTimestamp; // Block number or timestamp to use in the request
uint16 confirmations; // Number of block confirmations on top of the requested block number or timestamp before the view function can be called
address to; // Address of the target contract on the target chain
bytes callData; // Calldata for the contract call
}
struct EVMCallComputeV1 {
uint8 computeSetting; // Compute setting (0 = map only, 1 = reduce only, 2 = map reduce)
uint32 targetEid; // Target endpoint ID (representing a target blockchain)
bool isBlockNum; // True if the request = block number, false if timestamp
uint64 blockNumOrTimestamp; // Block number or timestamp to use in the request
uint16 confirmations; // Number of block confirmations on top of the requested block number or timestamp before the view function can be called
address to; // Address of the target contract on the target chain
}
library ReadCodecV1 {
using SafeCast for uint256;
uint16 internal constant CMD_VERSION = 1;
uint8 internal constant REQUEST_VERSION = 1;
uint16 internal constant RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL = 1;
uint8 internal constant COMPUTE_VERSION = 1;
uint16 internal constant COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL = 1;
error InvalidVersion();
error InvalidType();
function decode(
bytes calldata _cmd
)
internal
pure
returns (uint16 appCmdLabel, EVMCallRequestV1[] memory evmCallRequests, EVMCallComputeV1 memory compute)
{
uint256 offset = 0;
uint16 cmdVersion = uint16(bytes2(_cmd[offset:offset + 2]));
offset += 2;
if (cmdVersion != CMD_VERSION) revert InvalidVersion();
appCmdLabel = uint16(bytes2(_cmd[offset:offset + 2]));
offset += 2;
(evmCallRequests, offset) = decodeRequestsV1(_cmd, offset);
// decode the compute if it exists
if (offset < _cmd.length) {
(compute, ) = decodeEVMCallComputeV1(_cmd, offset);
}
}
function decodeRequestsV1(
bytes calldata _cmd,
uint256 _offset
) internal pure returns (EVMCallRequestV1[] memory evmCallRequests, uint256 newOffset) {
newOffset = _offset;
uint16 requestCount = uint16(bytes2(_cmd[newOffset:newOffset + 2]));
newOffset += 2;
evmCallRequests = new EVMCallRequestV1[](requestCount);
for (uint16 i = 0; i < requestCount; i++) {
uint8 requestVersion = uint8(_cmd[newOffset]);
newOffset += 1;
if (requestVersion != REQUEST_VERSION) revert InvalidVersion();
uint16 appRequestLabel = uint16(bytes2(_cmd[newOffset:newOffset + 2]));
newOffset += 2;
uint16 resolverType = uint16(bytes2(_cmd[newOffset:newOffset + 2]));
newOffset += 2;
if (resolverType == RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL) {
(EVMCallRequestV1 memory request, uint256 nextOffset) = decodeEVMCallRequestV1(
_cmd,
newOffset,
appRequestLabel
);
newOffset = nextOffset;
evmCallRequests[i] = request;
} else {
revert InvalidType();
}
}
}
function decodeEVMCallRequestV1(
bytes calldata _cmd,
uint256 _offset,
uint16 _appRequestLabel
) internal pure returns (EVMCallRequestV1 memory request, uint256 newOffset) {
newOffset = _offset;
request.appRequestLabel = _appRequestLabel;
uint16 requestSize = uint16(bytes2(_cmd[newOffset:newOffset + 2]));
newOffset += 2;
request.targetEid = uint32(bytes4(_cmd[newOffset:newOffset + 4]));
newOffset += 4;
request.isBlockNum = uint8(_cmd[newOffset]) == 1;
newOffset += 1;
request.blockNumOrTimestamp = uint64(bytes8(_cmd[newOffset:newOffset + 8]));
newOffset += 8;
request.confirmations = uint16(bytes2(_cmd[newOffset:newOffset + 2]));
newOffset += 2;
request.to = address(bytes20(_cmd[newOffset:newOffset + 20]));
newOffset += 20;
uint16 callDataSize = requestSize - 35;
request.callData = _cmd[newOffset:newOffset + callDataSize];
newOffset += callDataSize;
}
function decodeEVMCallComputeV1(
bytes calldata _cmd,
uint256 _offset
) internal pure returns (EVMCallComputeV1 memory compute, uint256 newOffset) {
newOffset = _offset;
uint8 computeVersion = uint8(_cmd[newOffset]);
newOffset += 1;
if (computeVersion != COMPUTE_VERSION) revert InvalidVersion();
uint16 computeType = uint16(bytes2(_cmd[newOffset:newOffset + 2]));
newOffset += 2;
if (computeType != COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL) revert InvalidType();
compute.computeSetting = uint8(_cmd[newOffset]);
newOffset += 1;
compute.targetEid = uint32(bytes4(_cmd[newOffset:newOffset + 4]));
newOffset += 4;
compute.isBlockNum = uint8(_cmd[newOffset]) == 1;
newOffset += 1;
compute.blockNumOrTimestamp = uint64(bytes8(_cmd[newOffset:newOffset + 8]));
newOffset += 8;
compute.confirmations = uint16(bytes2(_cmd[newOffset:newOffset + 2]));
newOffset += 2;
compute.to = address(bytes20(_cmd[newOffset:newOffset + 20]));
newOffset += 20;
}
function decodeCmdAppLabel(bytes calldata _cmd) internal pure returns (uint16) {
uint256 offset = 0;
uint16 cmdVersion = uint16(bytes2(_cmd[offset:offset + 2]));
offset += 2;
if (cmdVersion != CMD_VERSION) revert InvalidVersion();
return uint16(bytes2(_cmd[offset:offset + 2]));
}
function decodeRequestV1AppRequestLabel(bytes calldata _request) internal pure returns (uint16) {
uint256 offset = 0;
uint8 requestVersion = uint8(_request[offset]);
offset += 1;
if (requestVersion != REQUEST_VERSION) revert InvalidVersion();
return uint16(bytes2(_request[offset:offset + 2]));
}
function encode(
uint16 _appCmdLabel,
EVMCallRequestV1[] memory _evmCallRequests,
EVMCallComputeV1 memory _evmCallCompute
) internal pure returns (bytes memory) {
bytes memory cmd = encode(_appCmdLabel, _evmCallRequests);
if (_evmCallCompute.targetEid != 0) {
// if eid is 0, it means no compute
cmd = appendEVMCallComputeV1(cmd, _evmCallCompute);
}
return cmd;
}
function encode(
uint16 _appCmdLabel,
EVMCallRequestV1[] memory _evmCallRequests
) internal pure returns (bytes memory) {
bytes memory cmd = abi.encodePacked(CMD_VERSION, _appCmdLabel, _evmCallRequests.length.toUint16());
for (uint256 i = 0; i < _evmCallRequests.length; i++) {
cmd = appendEVMCallRequestV1(cmd, _evmCallRequests[i]);
}
return cmd;
}
// todo: optimize this with Buffer
function appendEVMCallRequestV1(
bytes memory _cmd,
EVMCallRequestV1 memory _request
) internal pure returns (bytes memory) {
bytes memory newCmd = abi.encodePacked(
_cmd,
REQUEST_VERSION,
_request.appRequestLabel,
RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL,
(_request.callData.length + 35).toUint16(),
_request.targetEid
);
return
abi.encodePacked(
newCmd,
_request.isBlockNum,
_request.blockNumOrTimestamp,
_request.confirmations,
_request.to,
_request.callData
);
}
function appendEVMCallComputeV1(
bytes memory _cmd,
EVMCallComputeV1 memory _compute
) internal pure returns (bytes memory) {
return
abi.encodePacked(
_cmd,
COMPUTE_VERSION,
COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL,
_compute.computeSetting,
_compute.targetEid,
_compute.isBlockNum,
_compute.blockNumOrTimestamp,
_compute.confirmations,
_compute.to
);
}
}
"
},
"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppRead.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { AddressCast } from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol";
import { OApp } from "./OApp.sol";
abstract contract OAppRead is OApp {
constructor(address _endpoint, address _delegate) OApp(_endpoint, _delegate) {}
// -------------------------------
// Only Owner
function setReadChannel(uint32 _channelId, bool _active) public virtual onlyOwner {
_setPeer(_channelId, _active ? AddressCast.toBytes32(address(this)) : bytes32(0));
}
}
"
},
"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppCore, ILayerZeroEndpointV2 } from "./interfaces/IOAppCore.sol";
/**
* @title OAppCore
* @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.
*/
abstract contract OAppCore is IOAppCore, Ownable {
// The LayerZero endpoint associated with the given OApp
ILayerZeroEndpointV2 public immutable endpoint;
// Mapping to store peers associated with corresponding endpoints
mapping(uint32 eid => bytes32 peer) public peers;
/**
* @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.
* @param _endpoint The address of the LOCAL Layer Zero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*
* @dev The delegate typically should be set as the owner of the contract.
*/
constructor(address _endpoint, address _delegate) {
endpoint = ILayerZeroEndpointV2(_endpoint);
if (_delegate == address(0)) revert InvalidDelegate();
endpoint.setDelegate(_delegate);
}
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
* @dev Set this to bytes32(0) to remove the peer address.
* @dev Peer is a bytes32 to accommodate non-evm chains.
*/
function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner {
_setPeer(_eid, _peer);
}
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*
* @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
* @dev Set this to bytes32(0) to remove the peer address.
* @dev Peer is a bytes32 to accommodate non-evm chains.
*/
function _setPeer(uint32 _eid, bytes32 _peer) internal virtual {
peers[_eid] = _peer;
emit PeerSet(_eid, _peer);
}
/**
* @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set.
* ie. the peer is set to bytes32(0).
* @param _eid The endpoint ID.
* @return peer The address of the peer associated with the specified endpoint.
*/
function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) {
bytes32 peer = peers[_eid];
if (peer == bytes32(0)) revert NoPeer(_eid);
return peer;
}
/**
* @notice Sets the delegate address for the OApp.
* @param _delegate The address of the delegate to be set.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.
*/
function setDelegate(address _delegate) public onlyOwner {
endpoint.setDelegate(_delegate);
}
}
"
},
"node_modules/@openzeppelin/contracts/access/Ownable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
"
},
"src/interfaces/IBridge.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IBridge {
error MissingOneTokenAddress();
error InvalidFunctionUseOtherSimilarName();
error InvalidDestinationBridge();
error InvalidReceiver();
error NotEnoughNativeToPayLayerZeroFee();
error OnlySafeGuard();
event OneBridged(uint64 indexed sourceChainid, address indexed to, uint256 amount);
function isChainLinked(uint64 _chainId) external view returns (bool);
function sendMessageAsController(uint32 _eid, uint32 _gasLimit, address _refundTo) external payable;
function estimateFee(uint32 _dstEid, uint256 _amount, uint32 _lzGasLimit) external view returns (uint256);
}
"
},
"src/interfaces/IController.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.0;
interface IController {
struct PeerStatus {
uint64 chainId;
uint32 lzEndpointId;
bytes32 peer;
uint32 requestTimeout;
uint8 failures;
bool succeed;
}
error PeerAlreadyExists();
event PeerLinkingCompleted(uint64 _toChainId);
function IsValidDestination(uint32 _dstEid) external view returns (bool);
}
"
},
"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
struct SetConfigParam {
uint32 eid;
uint32 configType;
bytes config;
}
interface IMessageLibManager {
struct Timeout {
address lib;
uint256 expiry;
}
event LibraryRegistered(address newLib);
event DefaultSendLibrarySet(uint32 eid, address newLib);
event DefaultReceiveLibrarySet(uint32 eid, address newLib);
event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry);
event SendLibrarySet(address sender, uint32 eid, address newLib);
event ReceiveLibrarySet(address receiver, uint32 eid, address newLib);
event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout);
function registerLibrary(address _lib) external;
function isRegisteredLibrary(address _lib) external view returns (bool);
function getRegisteredLibraries() external view returns (address[] memory);
function setDefaultSendLibrary(uint32 _eid, address _newLib) external;
function defaultSendLibrary(uint32 _eid) external view returns (address);
function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _gracePeriod) external;
function defaultReceiveLibrary(uint32 _eid) external view returns (address);
function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external;
function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry);
function isSupportedEid(uint32 _eid) external view returns (bool);
function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool);
/// ------------------- OApp interfaces -------------------
function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external;
function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib);
function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool);
function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external;
function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault);
function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _expiry) external;
function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry);
function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external;
function getConfig(
address _oapp,
address _lib,
uint32 _eid,
uint32 _configType
) external view returns (bytes memory config);
}
"
},
"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingComposer {
event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message);
event ComposeDelivered(address from, address to, bytes32 guid, uint16 index);
event LzComposeAlert(
address indexed from,
address indexed to,
address indexed executor,
bytes32 guid,
uint16 index,
uint256 gas,
uint256 value,
bytes message,
bytes extraData,
bytes reason
);
function composeQueue(
address _from,
address _to,
bytes32 _guid,
uint16 _index
) external view returns (bytes32 messageHash);
function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external;
function lzCompose(
address _from,
address _to,
bytes32 _guid,
uint16 _index,
bytes calldata _message,
bytes calldata _extraData
) external payable;
}
"
},
"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingChannel {
event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);
event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
function eid() external view returns (uint32);
// this is an emergency function if a message cannot be verified for some reasons
// required to provide _nextNonce to avoid race condition
function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;
function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);
function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);
function inboundPayloadHash(
address _receiver,
uint32 _srcEid,
bytes32 _sender,
uint64 _nonce
) external view returns (bytes32);
function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
}
"
},
"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingContext {
function isSendingMessage() external view returns (bool);
function getSendContext() external view returns (uint32 dstEid, address sender);
}
"
},
"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OAppSender
* @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.
*/
abstract contract OAppSender is OAppCore {
using SafeERC20 for IERC20;
// Custom error messages
error NotEnoughNative(uint256 msgValue);
error LzTokenUnavailable();
// @dev The version of the OAppSender implementation.
// @dev Version is bumped when changes are made to this contract.
uint64 internal constant SENDER_VERSION = 1;
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*
* @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented.
* ie. this is a SEND only OApp.
* @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions
*/
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
return (SENDER_VERSION, 0);
}
/**
* @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.
* @param _dstEid The destination endpoint ID.
* @param _message The message payload.
* @param _options Additional options for the message.
* @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens.
* @return fee The calculated MessagingFee for the message.
* - nativeFee: The native fee for the message.
* - lzTokenFee: The LZ token fee for the message.
*/
function _quote(
uint32 _dstEid,
bytes memory _message,
bytes memory _options,
bool _payInLzToken
) internal view virtual returns (MessagingFee memory fee) {
return
endpoint.quote(
MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken),
address(this)
);
}
/**
* @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message.
* @param _dstEid The destination endpoint ID.
* @param _message The message payload.
* @param _options Additional options for the message.
* @param _fee The calculated LayerZero fee for the message.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess fee values sent to the endpoint.
* @return receipt The receipt for the sent message.
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function _lzSend(
uint32 _dstEid,
bytes memory _message,
bytes memory _options,
MessagingFee memory _fee,
address _refundAddress
) internal virtual returns (MessagingReceipt memory receipt) {
// @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.
uint256 messageValue = _payNative(_fee.nativeFee);
if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);
return
// solhint-disable-next-line check-send-result
endpoint.send{ value: messageValue }(
MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),
_refundAddress
);
}
/**
* @dev Internal function to pay the native fee associated with the message.
* @param _nativeFee The native fee to be paid.
* @return nativeFee The amount of native currency paid.
*
* @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction,
* this will need to be overridden because msg.value would contain multiple lzFees.
* @dev Should be overridden in the event the LayerZero endpoint requires a different native currency.
* @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees.
* @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.
*/
function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) {
if (msg.value != _nativeFee) revert NotEnoughNative(msg.value);
return _nativeFee;
}
/**
* @dev Internal function to pay the LZ token fee associated with the message.
* @param _lzTokenFee The LZ token fee to be paid.
*
* @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.
* @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend().
*/
function _payLzToken(uint256 _lzTokenFee) internal virtual {
// @dev Cannot cache the token because it is not immutable in the endpoint.
address lzToken = endpoint.lzToken();
if (lzToken == address(0)) revert LzTokenUnavailable();
// Pay LZ token fee by sending tokens to the endpoint.
IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee);
}
}
"
},
"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { IOAppReceiver, Origin } from "./interfaces/IOAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OAppReceiver
* @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.
*/
abstract contract OAppReceiver is IOAppReceiver, OAppCore {
// Custom error message for when the caller is not the registered endpoint/
error OnlyEndpoint(address addr);
// @dev The version of the OAppReceiver implementation.
// @dev Version is bumped when changes are made to this contract.
uint64 internal constant RECEIVER_VERSION = 2;
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*
* @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented.
* ie. this is a RECEIVE only OApp.
* @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions.
*/
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
return (0, RECEIVER_VERSION);
}
/**
* @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
* @dev _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @dev _message The lzReceive payload.
* @param _sender The sender address.
* @return isSender Is a valid sender.
*
* @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer.
* @dev The default sender IS the OAppReceiver implementer.
*/
function isComposeMsgSender(
Origin calldata /*_origin*/,
bytes calldata /*_message*/,
address _sender
) public view virtual returns (bool) {
return _sender == address(this);
}
/**
* @notice Checks if the path initialization is allowed based on the provided origin.
* @param origin The origin information containing the source endpoint and sender address.
* @return Whether the path has been initialized.
*
* @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received.
* @dev This defaults to assuming if a peer has been set, its initialized.
* Can be overridden by the OApp if there is other logic to determine this.
*/
function allowInitializePath(Origin calldata origin) public view virtual returns (bool) {
return peers[origin.srcEid] == origin.sender;
}
/**
* @notice Retrieves the next nonce for a given source endpoint and sender address.
* @dev _srcEid The source endpoint ID.
* @dev _sender The sender address.
* @return nonce The next nonce.
*
* @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement.
* @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered.
* @dev This is also enforced by the OApp.
* @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0.
*/
function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) {
return 0;
}
/**
* @dev Entry point for receiving messages or packets from the endpoint.
* @param _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @param _guid The unique identifier for the received LayerZero message.
* @param _message The payload of the received message.
* @param _executor The address of the executor for the received message.
* @param _extraData Additional arbitrary data provided by the corresponding executor.
*
* @dev Entry point for receiving msg/packet from the LayerZero endpoint.
*/
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) public payable virtual {
// Ensures that only the endpoint can attempt to lzReceive() messages to this OApp.
if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender);
// Ensure that the sender matches the expected peer for the source endpoint.
if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender);
// Call the internal OApp implementation of lzReceive.
_lzReceive(_origin, _guid, _message, _executor, _extraData);
}
/**
* @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation.
*/
function _lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) internal virtual;
}
"
},
"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppOptionsType3.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @dev Struct representing enforced option parameters.
*/
struct EnforcedOptionParam {
uint32 eid; // Endpoint ID
uint16 msgType; // Message Type
bytes options; // Additional options
}
/**
* @title IOAppOptionsType3
* @dev Interface for the OApp with Type 3 Options, allowing the setting and combining of enforced options.
*/
interface IOAppOptionsType3 {
// Custom error message for invalid options
error InvalidOptions(bytes options);
// Event emitted when enforced options are set
event EnforcedOptionSet(EnforcedOptionParam[] _enforcedOptions);
/**
* @notice Sets enforced options for specific endpoint and message type combinations.
* @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
*/
function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) external;
/**
* @notice Combines options for a given endpoint and message type.
* @param _eid The endpoint ID.
* @param _msgType The OApp message type.
* @param _extraOptions Additional options passed by the caller.
* @return options The combination of caller specified options AND enforced options.
*/
function combineOptions(
uint32 _eid,
uint16 _msgType,
bytes calldata _extraOptions
) external view returns (bytes memory options);
}
"
},
"node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidi
Submitted on: 2025-09-19 11:03:35
Comments
Log in to comment.
No comments yet.