Source Code
Multichain Info
Latest 25 from a total of 307 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Send Credits | 44086381 | 155 days ago | IN | 0.3141281 CELO | 0.00802559 | ||||
| Send Credits | 44085351 | 155 days ago | IN | 122.69194745 CELO | 0.00782209 | ||||
| Send Credits | 44085351 | 155 days ago | IN | 2.09003514 CELO | 0.00782473 | ||||
| Send Credits | 44085351 | 155 days ago | IN | 5.94717555 CELO | 0.00788902 | ||||
| Send Credits | 44085050 | 155 days ago | IN | 1.97650752 CELO | 0.00782545 | ||||
| Send Credits | 44085050 | 155 days ago | IN | 5.94717555 CELO | 0.00788974 | ||||
| Withdraw Local | 43919876 | 157 days ago | IN | 0 CELO | 0.00156591 | ||||
| Deposit Local | 43919748 | 157 days ago | IN | 0 CELO | 0.00227934 | ||||
| Withdraw Local | 43919626 | 157 days ago | IN | 0 CELO | 0.00156591 | ||||
| Send Credits | 43919158 | 157 days ago | IN | 5.34369393 CELO | 0.00774573 | ||||
| Send Credits | 43919158 | 157 days ago | IN | 1.71859539 CELO | 0.00768144 | ||||
| Send Credits | 43919157 | 157 days ago | IN | 0.31078922 CELO | 0.00797968 | ||||
| Send Credits | 43919153 | 157 days ago | IN | 122.69194745 CELO | 0.0076788 | ||||
| Send Credits | 43917952 | 157 days ago | IN | 5.34369393 CELO | 0.00788974 | ||||
| Send Credits | 43917952 | 157 days ago | IN | 1.81842458 CELO | 0.00798463 | ||||
| Send Credits | 43917952 | 157 days ago | IN | 122.69194745 CELO | 0.00798235 | ||||
| Send Credits | 43916751 | 157 days ago | IN | 0.31056303 CELO | 0.00812369 | ||||
| Send | 43907881 | 157 days ago | IN | 0.24013663 CELO | 0.00767463 | ||||
| Send Credits | 43860952 | 157 days ago | IN | 122.69194745 CELO | 0.00782245 | ||||
| Send Credits | 43810852 | 158 days ago | IN | 122.69194745 CELO | 0.00782281 | ||||
| Send Credits | 43805152 | 158 days ago | IN | 122.69194745 CELO | 0.00782281 | ||||
| Send Credits | 43802160 | 158 days ago | IN | 122.69194745 CELO | 0.00782281 | ||||
| Send Credits | 43786251 | 158 days ago | IN | 122.69194745 CELO | 0.00782281 | ||||
| Send Credits | 43780252 | 158 days ago | IN | 122.69194745 CELO | 0.00782281 | ||||
| Send Credits | 43778757 | 158 days ago | IN | 122.69194745 CELO | 0.00782281 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 44086381 | 155 days ago | 0.3141281 CELO | ||||
| 44085351 | 155 days ago | 122.69194745 CELO | ||||
| 44085351 | 155 days ago | 2.09003514 CELO | ||||
| 44085351 | 155 days ago | 5.94717555 CELO | ||||
| 44085050 | 155 days ago | 1.97650752 CELO | ||||
| 44085050 | 155 days ago | 5.94717555 CELO | ||||
| 43919158 | 157 days ago | 5.34369393 CELO | ||||
| 43919158 | 157 days ago | 1.71859539 CELO | ||||
| 43919157 | 157 days ago | 0.31078922 CELO | ||||
| 43919153 | 157 days ago | 122.69194745 CELO | ||||
| 43917952 | 157 days ago | 5.34369393 CELO | ||||
| 43917952 | 157 days ago | 1.81842458 CELO | ||||
| 43917952 | 157 days ago | 122.69194745 CELO | ||||
| 43916751 | 157 days ago | 0.31056303 CELO | ||||
| 43907881 | 157 days ago | 0.24013663 CELO | ||||
| 43873911 | 157 days ago | 0.23979889 CELO | ||||
| 43873911 | 157 days ago | 0.23979889 CELO | ||||
| 43873646 | 157 days ago | 0.23979889 CELO | ||||
| 43873646 | 157 days ago | 0.23979889 CELO | ||||
| 43860952 | 157 days ago | 122.69194745 CELO | ||||
| 43810852 | 158 days ago | 122.69194745 CELO | ||||
| 43805152 | 158 days ago | 122.69194745 CELO | ||||
| 43802160 | 158 days ago | 122.69194745 CELO | ||||
| 43786251 | 158 days ago | 122.69194745 CELO | ||||
| 43780252 | 158 days ago | 122.69194745 CELO |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
UsdtOFT
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;
import { IERC20, SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IMessagingChannel } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol";
import { OApp, Origin } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OApp.sol";
import { OAppOptionsType3 } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/OAppOptionsType3.sol";
import { OFTLimit, OFTReceipt, OFTFeeDetail } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol";
import { IUsdtOFT, IOFT, SendParam, MessagingReceipt, MessagingFee } from "./IUsdtOFT.sol";
contract UsdtOFT is IUsdtOFT, OApp, OAppOptionsType3 {
using SafeERC20 for IERC20;
// MsgTypes
uint16 public constant WITHDRAW_REMOTE = 1;
uint16 public constant SEND_OFT = 2;
uint16 public constant SEND_CREDITS = 3;
// Endpoint IDs
uint32 public immutable ARBITRUM_EID; // 30110
uint32 public immutable CELO_EID; // 30125
uint32 public immutable ETH_EID; // 30101
uint32 public immutable TON_EID; // 30152
uint32 public immutable TRON_EID; // 30420
uint32 public immutable LOCAL_EID;
// Credit balances
mapping(uint32 eid => uint256 credits) public credits;
IERC20 internal immutable innerToken;
// Management addresses
address public lpAdmin;
address public planner;
// Fees
uint256 public feeBalance = 0;
uint16 public feeBps = 0;
uint16 public constant BPS_DENOMINATOR = 10000;
constructor(
uint32 _arbitrumEid,
uint32 _celoEid,
uint32 _ethEid,
uint32 _tonEid,
uint32 _tronEid,
address _token,
address _lzEndpoint,
address _delegate
) OApp(_lzEndpoint, _delegate) Ownable(_delegate) {
// @dev Endpoint details
ARBITRUM_EID = _arbitrumEid;
CELO_EID = _celoEid;
ETH_EID = _ethEid;
TON_EID = _tonEid;
TRON_EID = _tronEid;
LOCAL_EID = IMessagingChannel(_lzEndpoint).eid();
// @dev Only allow the contract to be deployed with the correct endpoint IDs
if (LOCAL_EID != ARBITRUM_EID && LOCAL_EID != CELO_EID && LOCAL_EID != ETH_EID && LOCAL_EID != TRON_EID) {
revert InvalidEid();
}
// @dev Token details
if (IERC20Metadata(_token).decimals() != sharedDecimals()) revert InvalidLocalDecimals();
innerToken = IERC20(_token);
// @dev Defaults to the lpAdmin AND planner being the delegate
lpAdmin = _delegate;
planner = _delegate;
}
modifier onlyLpAdminOrOwner() {
if (msg.sender != lpAdmin && msg.sender != owner()) revert OnlyLpAdminOrOwner();
_;
}
modifier onlyPlanner() {
if (msg.sender != planner) revert OnlyPlanner();
_;
}
/// ========================== INTERFACE FUNCTIONS =====================================
function token() public view returns (address) {
return address(innerToken);
}
function approvalRequired() external pure returns (bool) {
return true;
}
function oftVersion() external pure returns (bytes4 interfaceId, uint64 version) {
// @dev We are using version '0' to indicate that this is a custom oft implementation
return (type(IOFT).interfaceId, 0);
}
function sharedDecimals() public pure returns (uint8) {
return 6;
}
function tvl() external view returns (uint256) {
// @dev This will also account for tokens accidentally sent directly to this contract, but not accounted for.
return innerToken.balanceOf(address(this)) - feeBalance;
}
/// ========================== OWNER FUNCTIONS =====================================
function setLpAdmin(address _lpAdmin) external onlyOwner {
lpAdmin = _lpAdmin;
emit LpAdminSet(_lpAdmin);
}
function setPlanner(address _planner) external onlyOwner {
planner = _planner;
emit PlannerSet(_planner);
}
function setFeeBps(uint16 _feeBps) external onlyOwner {
// @dev Fees must be less than 100%
if (_feeBps >= BPS_DENOMINATOR) revert InvalidFeeBps(_feeBps);
feeBps = _feeBps;
emit FeeBpsSet(_feeBps);
}
function withdrawFees(address _to, uint256 _amount) external onlyOwner {
if (_amount > feeBalance) revert InsufficientFeeBalance();
feeBalance -= _amount;
if (LOCAL_EID == TRON_EID) {
// tron USDT does not support safeTransfer
innerToken.transfer(_to, _amount);
} else {
innerToken.safeTransfer(_to, _amount);
}
emit FeesWithdrawn(_to, _amount);
}
/// ========================== INTERNAL HELPER FUNCTIONS =====================================
function _assertCredits(uint32 _eid, uint256 _amount) internal view {
uint256 currentCredits = credits[_eid];
if (currentCredits < _amount) revert InsufficientCredits(_eid, currentCredits, _amount);
}
function _decreaseCredits(uint32 _eid, uint256 _amount) internal {
// @dev Only do the operation if its greater than 0;
if (_amount > 0) {
uint256 currentCredits = credits[_eid];
if (currentCredits < _amount) revert InsufficientCredits(_eid, currentCredits, _amount);
credits[_eid] = currentCredits - _amount;
}
}
function _increaseCredits(uint32 _eid, uint256 _amount) internal {
// @dev Only do the operation if its greater than 0;
if (_amount > 0) credits[_eid] += _amount;
}
function _buildMsgAndOptions(
uint16 _msgType,
SendParam calldata _sendParam,
uint256 _amount
) internal view returns (bytes memory message, bytes memory options) {
// @dev Can't move 0 tokens
if (_amount == 0) revert InvalidAmount();
// @dev this OFT does NOT support composing
if (_sendParam.composeMsg.length > 0) revert ComposeNotSupported();
// @dev Can safely cast this as uint64,
// because this is strictly used for USDT implementation where 6 decimals is used.
// Unless over 18 trillion usdt is minted, this wont be a problem.
message = abi.encodePacked(_msgType, _sendParam.to, uint64(_amount));
options = combineOptions(_sendParam.dstEid, _msgType, _sendParam.extraOptions);
}
/// ========================== LIQUIDITY FUNCTIONS =====================================
function depositLocal(uint256 _amount) external {
innerToken.safeTransferFrom(msg.sender, address(this), _amount);
_increaseCredits(LOCAL_EID, _amount);
emit LocalDeposit(_amount);
}
function withdrawLocal(address _to, uint256 _amount) external onlyLpAdminOrOwner {
_decreaseCredits(LOCAL_EID, _amount);
if (LOCAL_EID == TRON_EID) {
// tron USDT does not support safeTransfer
innerToken.transfer(_to, _amount);
} else {
innerToken.safeTransfer(_to, _amount);
}
emit LocalWithdrawn(_to, _amount);
}
function quoteWithdrawRemote(
SendParam calldata _sendParam,
bool _payInLzToken
) external view returns (MessagingFee memory msgFee) {
// @dev We use minAmountLd to follow same pattern as the TON implementation
_assertCredits(_sendParam.dstEid, _sendParam.minAmountLD);
(bytes memory message, bytes memory options) = _buildMsgAndOptions(
WITHDRAW_REMOTE,
_sendParam,
_sendParam.minAmountLD
);
// @dev Calculates the LayerZero fee for the withdrawRemote() operation.
return _quote(_sendParam.dstEid, message, options, _payInLzToken);
}
function withdrawRemote(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) external payable onlyLpAdminOrOwner returns (MessagingReceipt memory msgReceipt) {
// @dev We use minAmountLd to follow same pattern as the TON implementation
_decreaseCredits(_sendParam.dstEid, _sendParam.minAmountLD);
// @dev Generate the message and options
(bytes memory message, bytes memory options) = _buildMsgAndOptions(
WITHDRAW_REMOTE,
_sendParam,
_sendParam.minAmountLD
);
emit RemoteWithdrawn(_sendParam.dstEid, _sendParam.minAmountLD);
// @dev This is simply a send msg call, WITHOUT the debit logic being applied
return _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress);
}
/// ========================== CREDIT FUNCTIONS =====================================
function quoteSendCredits(
uint32 _dstEid,
uint64 _creditsArbitrum,
uint64 _creditsCelo,
uint64 _creditsEth,
uint64 _creditsTon,
uint64 _creditsTron,
bytes calldata _extraOptions,
bool _payInLzToken
) external view returns (MessagingFee memory msgFee) {
// @dev It's possible for the planner to send 0 totalCredits
_assertCredits(ARBITRUM_EID, _creditsArbitrum);
_assertCredits(CELO_EID, _creditsCelo);
_assertCredits(ETH_EID, _creditsEth);
_assertCredits(TON_EID, _creditsTon);
_assertCredits(TRON_EID, _creditsTron);
bytes memory message = abi.encodePacked(
SEND_CREDITS,
_creditsArbitrum,
_creditsCelo,
_creditsEth,
_creditsTon,
_creditsTron
);
bytes memory options = combineOptions(_dstEid, SEND_CREDITS, _extraOptions);
// @dev Calculates the LayerZero fee for the sendCredits() operation.
return _quote(_dstEid, message, options, _payInLzToken);
}
function sendCredits(
uint32 _dstEid,
uint64 _creditsArbitrum,
uint64 _creditsCelo,
uint64 _creditsEth,
uint64 _creditsTon,
uint64 _creditsTron,
bytes calldata _extraOptions,
MessagingFee calldata _fee
) external payable onlyPlanner returns (MessagingReceipt memory msgReceipt) {
// @dev It's possible for the planner to send 0 totalCredits
_decreaseCredits(ARBITRUM_EID, _creditsArbitrum);
_decreaseCredits(CELO_EID, _creditsCelo);
_decreaseCredits(ETH_EID, _creditsEth);
_decreaseCredits(TON_EID, _creditsTon);
_decreaseCredits(TRON_EID, _creditsTron);
bytes memory message = abi.encodePacked(
SEND_CREDITS,
_creditsArbitrum,
_creditsCelo,
_creditsEth,
_creditsTon,
_creditsTron
);
bytes memory options = combineOptions(_dstEid, SEND_CREDITS, _extraOptions);
emit CreditsSent(_dstEid, _creditsArbitrum, _creditsCelo, _creditsEth, _creditsTon, _creditsTron);
return _lzSend(_dstEid, message, options, _fee, msg.sender);
}
function _receiveCredits(bytes calldata _message) internal {
// @dev It's possible to receive 0 totalCredits
// @dev MsgType is ignored
uint64 _creditsArbitrum = uint64(bytes8(_message[2:10]));
uint64 _creditsCelo = uint64(bytes8(_message[10:18]));
uint64 _creditsEth = uint64(bytes8(_message[18:26]));
uint64 _creditsTon = uint64(bytes8(_message[26:34]));
uint64 _creditsTron = uint64(bytes8(_message[34:42]));
_increaseCredits(ARBITRUM_EID, _creditsArbitrum);
_increaseCredits(CELO_EID, _creditsCelo);
_increaseCredits(ETH_EID, _creditsEth);
_increaseCredits(TON_EID, _creditsTon);
_increaseCredits(TRON_EID, _creditsTron);
}
/// ========================== OFT FUNCTIONS =====================================
function _debitView(
uint256 _amount,
uint256 _minAmount
) internal view returns (uint256 amountSent, uint256 amountReceived) {
amountSent = _amount;
// @dev Apply the fee
uint256 feeAmount = (amountSent * feeBps) / BPS_DENOMINATOR;
amountReceived = amountSent - feeAmount;
// @dev Check for slippage.
if (amountReceived < _minAmount) revert SlippageExceeded(amountReceived, _minAmount);
}
function quoteOFT(
SendParam calldata _sendParam
)
external
view
virtual
returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt)
{
uint256 minAmount = 0;
uint256 maxAmount = type(uint64).max;
oftLimit = OFTLimit(minAmount, maxAmount);
// @dev Unused in this implementation
oftFeeDetails = new OFTFeeDetail[](0);
// @dev This is the same as the send() operation, but without the actual send.
// - amountSent is the amount that would be debited from the sender.
// - amountReceived is the amount that will be credited to the recipient.
// The diff is the fee amount to be applied
(uint256 amountSent, uint256 amountReceived) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD);
oftReceipt = OFTReceipt(amountSent, amountReceived);
}
// @dev The quote is as similar as possible to the actual send() operation.
function quoteSend(
SendParam calldata _sendParam,
bool _payInLzToken
) external view returns (MessagingFee memory msgFee) {
// @dev Mock the amount to receive, this is the same operation used in the send().
(, uint256 amountReceived) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD);
// @dev Handle the credits
_assertCredits(_sendParam.dstEid, amountReceived);
// @dev Builds the options and OFT message to quote in the endpoint.
(bytes memory message, bytes memory options) = _buildMsgAndOptions(SEND_OFT, _sendParam, amountReceived);
// @dev Calculates the LayerZero fee for the send() operation.
return _quote(_sendParam.dstEid, message, options, _payInLzToken);
}
function send(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) external payable returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) {
// @dev Applies fees and determines the total amount to deduct from the sender, and the amount received
(uint256 amountSent, uint256 amountReceived) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD);
// @dev Lock tokens by moving them into this contract from the caller.
innerToken.safeTransferFrom(msg.sender, address(this), amountSent);
// @dev Handle the credits
_decreaseCredits(_sendParam.dstEid, amountReceived);
_increaseCredits(LOCAL_EID, amountReceived);
// @dev Increment the fee balance so we can account for fee withdrawals
feeBalance += amountSent - amountReceived;
// @dev Generate the message and options
(bytes memory message, bytes memory options) = _buildMsgAndOptions(SEND_OFT, _sendParam, amountReceived);
// @dev Sends the message to the LayerZero endpoint and returns the LayerZero msg receipt.
msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress);
// @dev Formulate the OFT receipt.
oftReceipt = OFTReceipt(amountSent, amountReceived);
emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSent, amountReceived);
}
// Used for both OFT receive and withdrawRemote receive
function _receiveOFT(bytes calldata _message) internal returns (address to, uint256 amountReceived) {
// @dev Convert bytes 32 to an address
to = address(uint160(uint256(bytes32(_message[2:34]))));
amountReceived = uint64(bytes8(_message[34:42]));
// @dev Unlock the tokens and transfer to the recipient.
if (LOCAL_EID == TRON_EID) {
// tron USDT does not support safeTransfer
innerToken.transfer(to, amountReceived);
} else {
innerToken.safeTransfer(to, amountReceived);
}
}
/// ========================== LZ FUNCTIONS =====================================
function _lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address /*_executor*/,
bytes calldata /*_extraData*/
) internal virtual override {
// @dev Extract the msgType
uint16 msgType = uint16(bytes2(_message[0:2]));
if (msgType == SEND_CREDITS) {
_receiveCredits(_message);
emit CreditsReceived(_guid, _origin.srcEid, _message);
} else if (msgType == SEND_OFT) {
(address to, uint256 amountReceived) = _receiveOFT(_message);
emit OFTReceived(_guid, _origin.srcEid, to, amountReceived);
} else if (msgType == WITHDRAW_REMOTE) {
(address to, uint256 amountReceived) = _receiveOFT(_message);
emit RemoteWithdrawReceived(_guid, _origin.srcEid, to, amountReceived);
} else {
revert InvalidMsgType(msgType);
}
}
}// 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);
}
}// 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);
}
}// 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;
}// 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);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
/**
* @title IOAppCore
*/
interface IOAppCore {
// Custom error messages
error OnlyPeer(uint32 eid, bytes32 sender);
error NoPeer(uint32 eid);
error InvalidEndpointCall();
error InvalidDelegate();
// Event emitted when a peer (OApp) is set for a corresponding endpoint
event PeerSet(uint32 eid, bytes32 peer);
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*/
function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion);
/**
* @notice Retrieves the LayerZero endpoint associated with the OApp.
* @return iEndpoint The LayerZero endpoint as an interface.
*/
function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint);
/**
* @notice Retrieves the peer (OApp) associated with a corresponding endpoint.
* @param _eid The endpoint ID.
* @return peer The peer address (OApp instance) associated with the corresponding endpoint.
*/
function peers(uint32 _eid) external view returns (bytes32 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.
*/
function setPeer(uint32 _eid, bytes32 _peer) external;
/**
* @notice Sets the delegate address for the OApp Core.
* @param _delegate The address of the delegate to be set.
*/
function setDelegate(address _delegate) external;
}// 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);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol";
interface IOAppReceiver is ILayerZeroReceiver {
/**
* @notice Indicates whether an address is an approved composeMsg sender to 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 _message The lzReceive payload.
* @param _sender The sender address.
* @return isSender Is a valid sender.
*
* @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer.
* @dev The default sender IS the OAppReceiver implementer.
*/
function isComposeMsgSender(
Origin calldata _origin,
bytes calldata _message,
address _sender
) external view returns (bool isSender);
}// 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);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { MessagingReceipt, MessagingFee } from "../../oapp/OAppSender.sol";
/**
* @dev Struct representing token parameters for the OFT send() operation.
*/
struct SendParam {
uint32 dstEid; // Destination endpoint ID.
bytes32 to; // Recipient address.
uint256 amountLD; // Amount to send in local decimals.
uint256 minAmountLD; // Minimum amount to send in local decimals.
bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.
bytes composeMsg; // The composed message for the send() operation.
bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.
}
/**
* @dev Struct representing OFT limit information.
* @dev These amounts can change dynamically and are up the the specific oft implementation.
*/
struct OFTLimit {
uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient.
uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient.
}
/**
* @dev Struct representing OFT receipt information.
*/
struct OFTReceipt {
uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.
// @dev In non-default implementations, the amountReceivedLD COULD differ from this value.
uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.
}
/**
* @dev Struct representing OFT fee details.
* @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI.
*/
struct OFTFeeDetail {
int256 feeAmountLD; // Amount of the fee in local decimals.
string description; // Description of the fee.
}
/**
* @title IOFT
* @dev Interface for the OftChain (OFT) token.
* @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well.
* @dev This specific interface ID is '0x02e49c2c'.
*/
interface IOFT {
// Custom error messages
error InvalidLocalDecimals();
error SlippageExceeded(uint256 amountLD, uint256 minAmountLD);
// Events
event OFTSent(
bytes32 indexed guid, // GUID of the OFT message.
uint32 dstEid, // Destination Endpoint ID.
address indexed fromAddress, // Address of the sender on the src chain.
uint256 amountSentLD, // Amount of tokens sent in local decimals.
uint256 amountReceivedLD // Amount of tokens received in local decimals.
);
event OFTReceived(
bytes32 indexed guid, // GUID of the OFT message.
uint32 srcEid, // Source Endpoint ID.
address indexed toAddress, // Address of the recipient on the dst chain.
uint256 amountReceivedLD // Amount of tokens received in local decimals.
);
/**
* @notice Retrieves interfaceID and the version of the OFT.
* @return interfaceId The interface ID.
* @return version The version.
*
* @dev interfaceId: This specific interface ID is '0x02e49c2c'.
* @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
* @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
* ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
*/
function oftVersion() external view returns (bytes4 interfaceId, uint64 version);
/**
* @notice Retrieves the address of the token associated with the OFT.
* @return token The address of the ERC20 token implementation.
*/
function token() external view returns (address);
/**
* @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
* @return requiresApproval Needs approval of the underlying token implementation.
*
* @dev Allows things like wallet implementers to determine integration requirements,
* without understanding the underlying token implementation.
*/
function approvalRequired() external view returns (bool);
/**
* @notice Retrieves the shared decimals of the OFT.
* @return sharedDecimals The shared decimals of the OFT.
*/
function sharedDecimals() external view returns (uint8);
/**
* @notice Provides a quote for OFT-related operations.
* @param _sendParam The parameters for the send operation.
* @return limit The OFT limit information.
* @return oftFeeDetails The details of OFT fees.
* @return receipt The OFT receipt information.
*/
function quoteOFT(
SendParam calldata _sendParam
) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory);
/**
* @notice Provides a quote for the send() operation.
* @param _sendParam The parameters for the send() operation.
* @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.
* @return fee The calculated LayerZero messaging fee from the send() operation.
*
* @dev MessagingFee: LayerZero msg fee
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
*/
function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory);
/**
* @notice Executes the send() operation.
* @param _sendParam The parameters for the send operation.
* @param _fee The fee information supplied by the caller.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess funds from fees etc. on the src.
* @return receipt The LayerZero messaging receipt from the send() operation.
* @return oftReceipt The OFT receipt information.
*
* @dev MessagingReceipt: LayerZero msg receipt
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function send(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) external payable returns (MessagingReceipt memory, OFTReceipt memory);
}// 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;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { Origin } from "./ILayerZeroEndpointV2.sol";
interface ILayerZeroReceiver {
function allowInitializePath(Origin calldata _origin) external view returns (bool);
function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) external payable;
}// 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);
}// 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);
}// 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;
}// 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);
}// 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);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;
import { IOFT, SendParam, MessagingReceipt, MessagingFee } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol";
interface IUsdtOFT is IOFT {
/// ========================== EVENTS =====================================
event LpAdminSet(address lpAdmin);
event PlannerSet(address planner);
event FeeBpsSet(uint16 feeBps);
event FeesWithdrawn(address to, uint256 amount);
event LocalDeposit(uint256 amount);
event LocalWithdrawn(address to, uint256 amount);
event RemoteWithdrawn(uint32 dstEid, uint256 amount);
event RemoteWithdrawReceived(bytes32 guid, uint32 srcEid, address to, uint256 amount);
event CreditsSent(
uint32 dstEid,
uint64 creditsArbitrum,
uint64 creditsCelo,
uint64 creditsEth,
uint64 creditsTon,
uint64 creditsTron
);
event CreditsReceived(bytes32 guid, uint32 srcEid, bytes message);
/// ========================== ERRORS =====================================
error OnlyLpAdminOrOwner();
error OnlyPlanner();
error ComposeNotSupported();
error InvalidEid();
error InvalidMsgType(uint16 msgType);
error InvalidFeeBps(uint16 feeBps);
error InsufficientFeeBalance();
error InsufficientCredits(uint32 eid, uint256 credits, uint256 amountWithdraw);
error InvalidAmount();
/// ========================== GLOBAL VARIABLE FUNCTIONS =====================================
function credits(uint32 _eid) external view returns (uint256 credits);
function planner() external view returns (address);
function feeBps() external view returns (uint16);
function feeBalance() external view returns (uint256);
function tvl() external view returns (uint256);
/// ========================== OWNER FUNCTIONS =====================================
function setPlanner(address _planner) external;
function setFeeBps(uint16 _feeBps) external;
function withdrawFees(address _to, uint256 _amount) external;
/// ========================== LIQUIDITY FUNCTIONS =====================================
function depositLocal(uint256 _amount) external;
function withdrawLocal(address _to, uint256 _amount) external;
function quoteWithdrawRemote(
SendParam calldata _sendParam,
bool _payInLzToken
) external view returns (MessagingFee memory msgFee);
function withdrawRemote(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) external payable returns (MessagingReceipt memory msgReceipt);
/// ========================== CREDIT FUNCTIONS =====================================
function quoteSendCredits(
uint32 _dstEid,
uint64 _creditsArbitrum,
uint64 _creditsCelo,
uint64 _creditsEth,
uint64 _creditsTon,
uint64 _creditsTron,
bytes calldata _extraOptions,
bool _payInLzToken
) external view returns (MessagingFee memory msgFee);
function sendCredits(
uint32 _dstEid,
uint64 _creditsArbitrum,
uint64 _creditsCelo,
uint64 _creditsEth,
uint64 _creditsTon,
uint64 _creditsTron,
bytes calldata _extraOptions,
MessagingFee calldata _fee
) external payable returns (MessagingReceipt memory msgReceipt);
}{
"evmVersion": "paris",
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint32","name":"_arbitrumEid","type":"uint32"},{"internalType":"uint32","name":"_celoEid","type":"uint32"},{"internalType":"uint32","name":"_ethEid","type":"uint32"},{"internalType":"uint32","name":"_tonEid","type":"uint32"},{"internalType":"uint32","name":"_tronEid","type":"uint32"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_lzEndpoint","type":"address"},{"internalType":"address","name":"_delegate","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ComposeNotSupported","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint256","name":"credits","type":"uint256"},{"internalType":"uint256","name":"amountWithdraw","type":"uint256"}],"name":"InsufficientCredits","type":"error"},{"inputs":[],"name":"InsufficientFeeBalance","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEid","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[{"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"InvalidFeeBps","type":"error"},{"inputs":[],"name":"InvalidLocalDecimals","type":"error"},{"inputs":[{"internalType":"uint16","name":"msgType","type":"uint16"}],"name":"InvalidMsgType","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[],"name":"OnlyLpAdminOrOwner","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[],"name":"OnlyPlanner","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"}],"name":"SlippageExceeded","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"}],"name":"CreditsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":false,"internalType":"uint64","name":"creditsArbitrum","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"creditsCelo","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"creditsEth","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"creditsTon","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"creditsTron","type":"uint64"}],"name":"CreditsSent","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"indexed":false,"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"EnforcedOptionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"FeeBpsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LocalDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LocalWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lpAdmin","type":"address"}],"name":"LpAdminSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"planner","type":"address"}],"name":"PlannerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RemoteWithdrawReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RemoteWithdrawn","type":"event"},{"inputs":[],"name":"ARBITRUM_EID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CELO_EID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH_EID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCAL_EID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND_CREDITS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND_OFT","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TON_EID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRON_EID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITHDRAW_REMOTE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"approvalRequired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"uint16","name":"_msgType","type":"uint16"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"}],"name":"combineOptions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"credits","outputs":[{"internalType":"uint256","name":"credits","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositLocal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"}],"name":"enforcedOptions","outputs":[{"internalType":"bytes","name":"enforcedOption","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"isComposeMsgSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"oftVersion","outputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"},{"internalType":"uint64","name":"version","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"planner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"}],"name":"quoteOFT","outputs":[{"components":[{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"uint256","name":"maxAmountLD","type":"uint256"}],"internalType":"struct OFTLimit","name":"oftLimit","type":"tuple"},{"components":[{"internalType":"int256","name":"feeAmountLD","type":"int256"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct OFTFeeDetail[]","name":"oftFeeDetails","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quoteSend","outputs":[{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"msgFee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint64","name":"_creditsArbitrum","type":"uint64"},{"internalType":"uint64","name":"_creditsCelo","type":"uint64"},{"internalType":"uint64","name":"_creditsEth","type":"uint64"},{"internalType":"uint64","name":"_creditsTon","type":"uint64"},{"internalType":"uint64","name":"_creditsTron","type":"uint64"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quoteSendCredits","outputs":[{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"msgFee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quoteWithdrawRemote","outputs":[{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"msgFee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"_fee","type":"tuple"},{"internalType":"address","name":"_refundAddress","type":"address"}],"name":"send","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint64","name":"_creditsArbitrum","type":"uint64"},{"internalType":"uint64","name":"_creditsCelo","type":"uint64"},{"internalType":"uint64","name":"_creditsEth","type":"uint64"},{"internalType":"uint64","name":"_creditsTon","type":"uint64"},{"internalType":"uint64","name":"_creditsTron","type":"uint64"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"_fee","type":"tuple"}],"name":"sendCredits","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"setEnforcedOptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_feeBps","type":"uint16"}],"name":"setFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lpAdmin","type":"address"}],"name":"setLpAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_planner","type":"address"}],"name":"setPlanner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sharedDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tvl","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawLocal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"_fee","type":"tuple"},{"internalType":"address","name":"_refundAddress","type":"address"}],"name":"withdrawRemote","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"}]Contract Creation Code
61018060405260006006556007805461ffff191690553480156200002257600080fd5b5060405162003ee138038062003ee1833981016040819052620000459162000384565b81818181806001600160a01b0381166200007957604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b620000848162000302565b506001600160a01b038083166080528116620000b357604051632d618d8160e21b815260040160405180910390fd5b60805160405163ca5eb5e160e01b81526001600160a01b0383811660048301529091169063ca5eb5e190602401600060405180830381600087803b158015620000fb57600080fd5b505af115801562000110573d6000803e3d6000fd5b50505063ffffffff808e1660a0528c811660c0528b811660e0528a81166101005289166101205250506040805163416ecebf60e01b815290516001600160a01b038716945063416ecebf9350600480830193506020928290030181865afa15801562000180573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001a691906200042c565b63ffffffff90811661014081905260a05190911614801590620001da575060c05163ffffffff166101405163ffffffff1614155b8015620001f8575060e05163ffffffff166101405163ffffffff1614155b80156200021757506101205163ffffffff166101405163ffffffff1614155b156200023657604051634d30e69360e11b815260040160405180910390fd5b600660ff16836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200027a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002a0919062000451565b60ff1614620002c2576040516301e9714b60e41b815260040160405180910390fd5b6001600160a01b0392831661016052600480546001600160a01b031990811692909416918217905560058054909316179091555062000476945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b805163ffffffff811681146200036757600080fd5b919050565b80516001600160a01b03811681146200036757600080fd5b600080600080600080600080610100898b031215620003a257600080fd5b620003ad8962000352565b9750620003bd60208a0162000352565b9650620003cd60408a0162000352565b9550620003dd60608a0162000352565b9450620003ed60808a0162000352565b9350620003fd60a08a016200036c565b92506200040d60c08a016200036c565b91506200041d60e08a016200036c565b90509295985092959890939650565b6000602082840312156200043f57600080fd5b6200044a8262000352565b9392505050565b6000602082840312156200046457600080fd5b815160ff811681146200044a57600080fd5b60805160a05160c05160e051610100516101205161014051610160516138f4620005ed6000396000818161094801528181610d5c01528181610ddc015281816112e00152818161141f0152818161149f0152818161180a01528181611a5e0152818161263001526126b001526000818161091701528181610cbe01528181610d0c0152818161130d015281816113cf0152818161184d01526125e001526000818161050401528181610ce501528181610fd4015281816111e1015281816113a80152818161254801526125b901526000818161048301528181610fa1015281816111ae01526125150152600081816103ae01528181610f6e0152818161117b01526124e201526000818161061c01528181610f3b0152818161114801526124af0152600081816103f701528181610f0801528181611115015261247c01526000818161056501528181610b2c0152818161197401528181611f47015281816121630152818161276d015261282601526138f46000f3fe6080604052600436106102935760003560e01c806382413eac1161015a578063bb0b6a53116100c1578063e5328e061161007a578063e5328e06146108b0578063ed9445d4146108c5578063f2fde38b146108e5578063f368ce2114610905578063fc0c546a14610939578063ff7bd03d1461096c57600080fd5b8063bb0b6a53146107ec578063bc70b35414610819578063c7c7f5b314610839578063ca5eb5e11461085a578063dbad31d61461087a578063e1a452181461089a57600080fd5b80639de36096116101135780639de36096146107505780639f68b96414610765578063a363b94514610779578063ad3b1b4714610799578063b98bd070146107b9578063b9e5567c146107d957600080fd5b806382413eac14610679578063826f1fb1146106a9578063857749b0146106c95780638da5cb5b146106e55780639ce704ee146107035780639d1580b41461072357600080fd5b80633b6f743b116101fe57806361d488af116101b757806361d488af146105ab5780636c0c85df146105c0578063715018a6146105e057806376a499f0146105f55780637b1e22c11461060a5780637d25a05e1461063e57600080fd5b80633b6f743b146104a557806342bdf044146104d257806354ddfe22146104f25780635535d461146105265780635e280f111461055357806360b71d4e1461058757600080fd5b806324a9d8531161025057806324a9d8531461036e57806325996dae1461039c5780632868f841146103e557806332e4e363146104195780633400288b1461045157806336ec8a221461047157600080fd5b8063023b1fc9146102985780630c7636aa146102ba5780630d35b415146102da57806313137d6514610312578063156a0d0f1461032557806317442b701461034c575b600080fd5b3480156102a457600080fd5b506102b86102b33660046129a1565b61098c565b005b3480156102c657600080fd5b506102b86102d53660046129d1565b610a10565b3480156102e657600080fd5b506102fa6102f5366004612a06565b610a66565b60405161030993929190612a8a565b60405180910390f35b6102b8610320366004612b76565b610b2a565b34801561033157600080fd5b506040805162b9270b60e21b81526000602082015201610309565b34801561035857600080fd5b5060408051600181526002602082015201610309565b34801561037a57600080fd5b506007546103899061ffff1681565b60405161ffff9091168152602001610309565b3480156103a857600080fd5b506103d07f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610309565b3480156103f157600080fd5b506103d07f000000000000000000000000000000000000000000000000000000000000000081565b34801561042557600080fd5b50600554610439906001600160a01b031681565b6040516001600160a01b039091168152602001610309565b34801561045d57600080fd5b506102b861046c366004612c29565b610be5565b34801561047d57600080fd5b506103d07f000000000000000000000000000000000000000000000000000000000000000081565b3480156104b157600080fd5b506104c56104c0366004612c61565b610bfb565b6040516103099190612cb2565b3480156104de57600080fd5b506102b86104ed366004612cc9565b610c75565b3480156104fe57600080fd5b506103d07f000000000000000000000000000000000000000000000000000000000000000081565b34801561053257600080fd5b50610546610541366004612ce7565b610e4a565b6040516103099190612d1a565b34801561055f57600080fd5b506104397f000000000000000000000000000000000000000000000000000000000000000081565b34801561059357600080fd5b5061059d60065481565b604051908152602001610309565b3480156105b757600080fd5b50610389600281565b3480156105cc57600080fd5b506104c56105db366004612d42565b610eef565b3480156105ec57600080fd5b506102b861105e565b34801561060157600080fd5b50610389600381565b34801561061657600080fd5b506103d07f000000000000000000000000000000000000000000000000000000000000000081565b34801561064a57600080fd5b50610661610659366004612c29565b600092915050565b6040516001600160401b039091168152602001610309565b34801561068557600080fd5b50610699610694366004612e06565b611072565b6040519015158152602001610309565b3480156106b557600080fd5b506102b86106c43660046129d1565b611087565b3480156106d557600080fd5b5060405160068152602001610309565b3480156106f157600080fd5b506000546001600160a01b0316610439565b610716610711366004612e7e565b6110dd565b6040516103099190612f73565b34801561072f57600080fd5b5061059d61073e366004612f81565b60036020526000908152604090205481565b34801561075c57600080fd5b50610389600181565b34801561077157600080fd5b506001610699565b34801561078557600080fd5b506102b8610794366004612f9c565b6112d3565b3480156107a557600080fd5b506102b86107b4366004612cc9565b611362565b3480156107c557600080fd5b506102b86107d4366004612fb5565b611505565b6107166107e7366004613029565b61151f565b3480156107f857600080fd5b5061059d610807366004612f81565b60016020526000908152604090205481565b34801561082557600080fd5b5061054661083436600461308b565b61161f565b61084c610847366004613029565b6117c7565b6040516103099291906130eb565b34801561086657600080fd5b506102b86108753660046129d1565b61194d565b34801561088657600080fd5b506104c5610895366004612c61565b6119d3565b3480156108a657600080fd5b5061038961271081565b3480156108bc57600080fd5b5061059d611a3a565b3480156108d157600080fd5b50600454610439906001600160a01b031681565b3480156108f157600080fd5b506102b86109003660046129d1565b611ad8565b34801561091157600080fd5b506103d07f000000000000000000000000000000000000000000000000000000000000000081565b34801561094557600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610439565b34801561097857600080fd5b5061069961098736600461310f565b611b16565b610994611b4c565b61271061ffff8216106109c557604051632b0caee160e01b815261ffff821660048201526024015b60405180910390fd5b6007805461ffff191661ffff83169081179091556040519081527f9bcf94806ecd549c5fde16e51a1aa08969f40766e486082ffa0776f594ceeba0906020015b60405180910390a150565b610a18611b4c565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f77dc8c64df705e1cadda346c392c907893d3513bc4cf95865b2ca90b793a78de90602001610a05565b60408051808201909152600080825260208201526060610a99604051806040016040528060008152602001600081525090565b60408051808201825260008082526001600160401b03602080840182905284518381529081019094529195509182610af4565b604080518082019091526000815260606020820152815260200190600190039081610acc5790505b509350600080610b0c88604001358960600135611b79565b60408051808201909152918252602082015296989597505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610b75576040516391ac5e4f60e01b81523360048201526024016109bc565b60208701803590610b8f90610b8a908a612f81565b611be0565b14610bcd57610ba16020880188612f81565b60405163309afaf360e21b815263ffffffff9091166004820152602088013560248201526044016109bc565b610bdc87878787878787611c1c565b50505050505050565b610bed611b4c565b610bf78282611dc9565b5050565b60408051808201909152600080825260208201526000610c2384604001358560600135611b79565b9150610c3d9050610c376020860186612f81565b82611e17565b600080610c4c60028785611e69565b9092509050610c69610c616020880188612f81565b838388611f31565b93505050505b92915050565b6004546001600160a01b03163314801590610c9b57506000546001600160a01b03163314155b15610cb95760405163f24eb55560e01b815260040160405180910390fd5b610ce37f000000000000000000000000000000000000000000000000000000000000000082612009565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff1603610dcf5760405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610da5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc99190613141565b50610e03565b610e036001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168383612081565b604080516001600160a01b0384168152602081018390527fb553c27b290d117801add9bfe5b9c82655aaa3f3b1ff88f04e8062e53985429a91015b60405180910390a15050565b600260209081526000928352604080842090915290825290208054610e6e9061315e565b80601f0160208091040260200160405190810160405280929190818152602001828054610e9a9061315e565b8015610ee75780601f10610ebc57610100808354040283529160200191610ee7565b820191906000526020600020905b815481529060010190602001808311610eca57829003601f168201915b505050505081565b6040805180820190915260008082526020820152610f367f00000000000000000000000000000000000000000000000000000000000000008a6001600160401b0316611e17565b610f697f0000000000000000000000000000000000000000000000000000000000000000896001600160401b0316611e17565b610f9c7f0000000000000000000000000000000000000000000000000000000000000000886001600160401b0316611e17565b610fcf7f0000000000000000000000000000000000000000000000000000000000000000876001600160401b0316611e17565b6110027f0000000000000000000000000000000000000000000000000000000000000000866001600160401b0316611e17565b600060038a8a8a8a8a60405160200161102096959493929190613192565b604051602081830303815290604052905060006110408c6003888861161f565b905061104e8c838387611f31565b9c9b505050505050505050505050565b611066611b4c565b61107060006120e0565b565b6001600160a01b03811630145b949350505050565b61108f611b4c565b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f5767d79cd17d7554509a4dd59a5a7a9175c7e36466455d7b2fa478822880857990602001610a05565b6110e5612943565b6005546001600160a01b031633146111105760405163061af57960e01b815260040160405180910390fd5b6111437f00000000000000000000000000000000000000000000000000000000000000008a6001600160401b0316612009565b6111767f0000000000000000000000000000000000000000000000000000000000000000896001600160401b0316612009565b6111a97f0000000000000000000000000000000000000000000000000000000000000000886001600160401b0316612009565b6111dc7f0000000000000000000000000000000000000000000000000000000000000000876001600160401b0316612009565b61120f7f0000000000000000000000000000000000000000000000000000000000000000866001600160401b0316612009565b600060038a8a8a8a8a60405160200161122d96959493929190613192565b6040516020818303038152906040529050600061124d8c6003888861161f565b6040805163ffffffff8f1681526001600160401b038e811660208301528d8116828401528c811660608301528b811660808301528a1660a082015290519192507f39d01394877aa469089f52f91bc8ff4d57872b2ccf0dfeecd086051d1e973bee919081900360c00190a161104e8c83836112cd36899003890189613260565b33612130565b6113086001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633308461223b565b6113327f00000000000000000000000000000000000000000000000000000000000000008261227a565b6040518181527f54ff32c5fe6e04031abcc9d0c05fb2c146df6f5aad45f3d7d06f1e21c9f6bbfb90602001610a05565b61136a611b4c565b60065481111561138d57604051637806a4f560e11b815260040160405180910390fd5b806006600082825461139f91906132a8565b925050819055507f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff16036114925760405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015611468573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148c9190613141565b506114c6565b6114c66001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168383612081565b604080516001600160a01b0384168152602081018390527fc0819c13be868895eb93e40eaceb96de976442fa1d404e5c55f14bb65a8c489a9101610e3e565b61150d611b4c565b610bf761151a82846132bb565b6122ae565b611527612943565b6004546001600160a01b0316331480159061154d57506000546001600160a01b03163314155b1561156b5760405163f24eb55560e01b815260040160405180910390fd5b61158561157b6020860186612f81565b8560600135612009565b6000806115986001878860600135611e69565b90925090507fc67a11a48e2fbc72ed25165a3c32149b773e5ff8d498ec24615f4b47d66f839c6115cb6020880188612f81565b6040805163ffffffff9092168252606089013560208301520160405180910390a16116136115fc6020880188612f81565b838361160d368a90038a018a613260565b88612130565b925050505b9392505050565b63ffffffff8416600090815260026020908152604080832061ffff871684529091528120805460609291906116539061315e565b80601f016020809104026020016040519081016040528092919081815260200182805461167f9061315e565b80156116cc5780601f106116a1576101008083540402835291602001916116cc565b820191906000526020600020905b8154815290600101906020018083116116af57829003601f168201915b50505050509050805160000361171c5783838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092945061107f9350505050565b600083900361172c57905061107f565b600283106117aa5761177384848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506123b592505050565b8061178184600281886133e0565b6040516020016117939392919061340a565b60405160208183030381529060405291505061107f565b8383604051639a6d49cd60e01b81526004016109bc92919061345b565b6117cf612943565b60408051808201909152600080825260208201526000806117f887604001358860600135611b79565b90925090506118326001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633308561223b565b6118486118426020890189612f81565b82612009565b6118727f00000000000000000000000000000000000000000000000000000000000000008261227a565b61187c81836132a8565b6006600082825461188d919061346f565b9091555060009050806118a260028a85611e69565b90925090506118ce6118b760208b018b612f81565b83836118c8368d90038d018d613260565b8b612130565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a9061191c908d018d612f81565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b611955611b4c565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e190602401600060405180830381600087803b1580156119b857600080fd5b505af11580156119cc573d6000803e3d6000fd5b5050505050565b6040805180820190915260008082526020820152611a016119f76020850185612f81565b8460600135611e17565b600080611a146001868760600135611e69565b9092509050611a31611a296020870187612f81565b838387611f31565b95945050505050565b6006546040516370a0823160e01b8152306004820152600091906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611aa5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac99190613482565b611ad391906132a8565b905090565b611ae0611b4c565b6001600160a01b038116611b0a57604051631e4fbdf760e01b8152600060048201526024016109bc565b611b13816120e0565b50565b6000602082018035906001908390611b2e9086612f81565b63ffffffff1681526020810191909152604001600020541492915050565b6000546001600160a01b031633146110705760405163118cdaa760e01b81523360048201526024016109bc565b6007548290600090819061271090611b959061ffff168561349b565b611b9f91906134b2565b9050611bab81846132a8565b915083821015611bd8576040516371c4efed60e01b815260048101839052602481018590526044016109bc565b509250929050565b63ffffffff811660009081526001602052604081205480610c6f5760405163f6ff4fb760e01b815263ffffffff841660048201526024016109bc565b6000611c2b60028287896133e0565b611c34916134d4565b60f01c90506002198101611c9a57611c4c86866123e1565b7f3db8474102b857712fc19a9142f559c0b9c2dd375fa0c50626bfa44eab47480187611c7b60208b018b612f81565b8888604051611c8d9493929190613504565b60405180910390a1611dbf565b60011961ffff821601611d1757600080611cb48888612576565b90925090506001600160a01b038216897fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c611cf260208e018e612f81565b6040805163ffffffff9092168252602082018690520160405180910390a35050611dbf565b60001961ffff821601611da057600080611d318888612576565b90925090507f3f42e057866db95fa13dd768aa8e103200d6ac6e7af2d51fff21fc32dc0be69489611d6560208d018d612f81565b6040805192835263ffffffff90911660208301526001600160a01b038516908201526060810183905260800160405180910390a15050611dbf565b60405163a7ac386360e01b815261ffff821660048201526024016109bc565b5050505050505050565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b9101610e3e565b63ffffffff821660009081526003602052604090205481811015611e645760405163735f7cd760e01b815263ffffffff8416600482015260248101829052604481018390526064016109bc565b505050565b60608082600003611e8d5760405163162908e360e11b815260040160405180910390fd5b6000611e9c60a0860186613534565b90501115611ebd57604051630b45411560e11b815260040160405180910390fd5b6040516001600160f01b031960f087901b1660208281019190915285013560228201526001600160c01b031960c085901b166042820152604a0160408051601f198184030181529190529150611f27611f196020860186612f81565b866108346080880188613534565b9050935093915050565b60408051808201909152600080825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611f9489611be0565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611fc992919061357a565b6040805180830381865afa158015611fe5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a319190613623565b8015610bf75763ffffffff82166000908152600360205260409020548181101561205c5760405163735f7cd760e01b815263ffffffff8416600482015260248101829052604481018390526064016109bc565b61206682826132a8565b63ffffffff8416600090815260036020526040902055505050565b6040516001600160a01b03838116602483015260448201839052611e6491859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506126de565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612138612943565b60006121478460000151612741565b602085015190915015612161576121618460200151612769565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016121b18c611be0565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b81526004016121ed92919061357a565b60806040518083038185885af115801561220b573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612230919061363f565b979650505050505050565b6040516001600160a01b0384811660248301528381166044830152606482018390526122749186918216906323b872dd906084016120ae565b50505050565b8015610bf75763ffffffff8216600090815260036020526040812080548392906122a590849061346f565b90915550505050565b60005b8151811015612385576122e08282815181106122cf576122cf613689565b6020026020010151604001516123b5565b8181815181106122f2576122f2613689565b6020026020010151604001516002600084848151811061231457612314613689565b60200260200101516000015163ffffffff1663ffffffff168152602001908152602001600020600084848151811061234e5761234e613689565b60200260200101516020015161ffff1661ffff168152602001908152602001600020908161237c91906136ef565b506001016122b1565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610a0591906137ae565b600281015161ffff8116600314610bf75781604051639a6d49cd60e01b81526004016109bc9190612d1a565b60006123f1600a600284866133e0565b6123fa91613839565b60c01c9050600061240f6012600a85876133e0565b61241891613839565b60c01c9050600061242d601a601286886133e0565b61243691613839565b60c01c9050600061244b6022601a87896133e0565b61245491613839565b60c01c90506000612469602a6022888a6133e0565b61247291613839565b60c01c90506124aa7f0000000000000000000000000000000000000000000000000000000000000000866001600160401b031661227a565b6124dd7f0000000000000000000000000000000000000000000000000000000000000000856001600160401b031661227a565b6125107f0000000000000000000000000000000000000000000000000000000000000000846001600160401b031661227a565b6125437f0000000000000000000000000000000000000000000000000000000000000000836001600160401b031661227a565b610bdc7f0000000000000000000000000000000000000000000000000000000000000000826001600160401b031661227a565b6000806125876022600285876133e0565b61259091613867565b91506125a0602a602285876133e0565b6125a991613839565b60c01c6001600160401b031690507f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff16036126a35760405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269d9190613141565b506126d7565b6126d76001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168383612081565b9250929050565b60006126f36001600160a01b0384168361284b565b905080516000141580156127185750808060200190518101906127169190613141565b155b15611e6457604051635274afe760e01b81526001600160a01b03841660048201526024016109bc565b6000813414612765576040516304fb820960e51b81523460048201526024016109bc565b5090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ed9190613885565b90506001600160a01b038116612816576040516329b99a9560e11b815260040160405180910390fd5b610bf76001600160a01b038216337f00000000000000000000000000000000000000000000000000000000000000008561223b565b60606116188383600084600080856001600160a01b0316848660405161287191906138a2565b60006040518083038185875af1925050503d80600081146128ae576040519150601f19603f3d011682016040523d82523d6000602084013e6128b3565b606091505b50915091506116138683836060826128d3576128ce8261291a565b611618565b81511580156128ea57506001600160a01b0384163b155b1561291357604051639996b31560e01b81526001600160a01b03851660048201526024016109bc565b5080611618565b80511561292a5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60405180606001604052806000801916815260200160006001600160401b03168152602001612985604051806040016040528060008152602001600081525090565b905290565b803561ffff8116811461299c57600080fd5b919050565b6000602082840312156129b357600080fd5b6116188261298a565b6001600160a01b0381168114611b1357600080fd5b6000602082840312156129e357600080fd5b8135611618816129bc565b600060e08284031215612a0057600080fd5b50919050565b600060208284031215612a1857600080fd5b81356001600160401b03811115612a2e57600080fd5b61107f848285016129ee565b60005b83811015612a55578181015183820152602001612a3d565b50506000910152565b60008151808452612a76816020860160208601612a3a565b601f01601f19169290920160200192915050565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b83811015612b055788870360bf19018552815180518852830151838801879052612af287890182612a5e565b9750509382019390820190600101612ac6565b5050875160608801525050506020850151608085015250905061107f565b600060608284031215612a0057600080fd5b60008083601f840112612b4757600080fd5b5081356001600160401b03811115612b5e57600080fd5b6020830191508360208285010111156126d757600080fd5b600080600080600080600060e0888a031215612b9157600080fd5b612b9b8989612b23565b96506060880135955060808801356001600160401b0380821115612bbe57600080fd5b612bca8b838c01612b35565b909750955060a08a01359150612bdf826129bc565b90935060c08901359080821115612bf557600080fd5b50612c028a828b01612b35565b989b979a50959850939692959293505050565b803563ffffffff8116811461299c57600080fd5b60008060408385031215612c3c57600080fd5b612c4583612c15565b946020939093013593505050565b8015158114611b1357600080fd5b60008060408385031215612c7457600080fd5b82356001600160401b03811115612c8a57600080fd5b612c96858286016129ee565b9250506020830135612ca781612c53565b809150509250929050565b815181526020808301519082015260408101610c6f565b60008060408385031215612cdc57600080fd5b8235612c45816129bc565b60008060408385031215612cfa57600080fd5b612d0383612c15565b9150612d116020840161298a565b90509250929050565b6020815260006116186020830184612a5e565b6001600160401b0381168114611b1357600080fd5b60008060008060008060008060006101008a8c031215612d6157600080fd5b612d6a8a612c15565b985060208a0135612d7a81612d2d565b975060408a0135612d8a81612d2d565b965060608a0135612d9a81612d2d565b955060808a0135612daa81612d2d565b945060a08a0135612dba81612d2d565b935060c08a01356001600160401b03811115612dd557600080fd5b612de18c828d01612b35565b90945092505060e08a0135612df581612c53565b809150509295985092959850929598565b60008060008060a08587031215612e1c57600080fd5b612e268686612b23565b935060608501356001600160401b03811115612e4157600080fd5b612e4d87828801612b35565b9094509250506080850135612e61816129bc565b939692955090935050565b600060408284031215612a0057600080fd5b60008060008060008060008060006101208a8c031215612e9d57600080fd5b612ea68a612c15565b985060208a0135612eb681612d2d565b975060408a0135612ec681612d2d565b965060608a0135612ed681612d2d565b955060808a0135612ee681612d2d565b945060a08a0135612ef681612d2d565b935060c08a01356001600160401b03811115612f1157600080fd5b612f1d8c828d01612b35565b9094509250612f3190508b60e08c01612e6c565b90509295985092959850929598565b805182526001600160401b0360208201511660208301526040810151611e64604084018280518252602090810151910152565b60808101610c6f8284612f40565b600060208284031215612f9357600080fd5b61161882612c15565b600060208284031215612fae57600080fd5b5035919050565b60008060208385031215612fc857600080fd5b82356001600160401b0380821115612fdf57600080fd5b818501915085601f830112612ff357600080fd5b81358181111561300257600080fd5b8660208260051b850101111561301757600080fd5b60209290920196919550909350505050565b60008060006080848603121561303e57600080fd5b83356001600160401b0381111561305457600080fd5b613060868287016129ee565b9350506130708560208601612e6c565b91506060840135613080816129bc565b809150509250925092565b600080600080606085870312156130a157600080fd5b6130aa85612c15565b93506130b86020860161298a565b925060408501356001600160401b038111156130d357600080fd5b6130df87828801612b35565b95989497509550505050565b60c081016130f98285612f40565b82516080830152602083015160a0830152611618565b60006060828403121561312157600080fd5b6116188383612b23565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561315357600080fd5b815161161881612c53565b600181811c9082168061317257607f821691505b602082108103612a0057634e487b7160e01b600052602260045260246000fd5b60f09690961b6001600160f01b031916865260c094851b6001600160c01b0319908116600288015293851b8416600a87015291841b83166012860152831b8216601a85015290911b166022820152602a0190565b604080519081016001600160401b03811182821017156132085761320861312b565b60405290565b604051606081016001600160401b03811182821017156132085761320861312b565b604051601f8201601f191681016001600160401b03811182821017156132585761325861312b565b604052919050565b60006040828403121561327257600080fd5b61327a6131e6565b82358152602083013560208201528091505092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c6f57610c6f613292565b60006001600160401b03808411156132d5576132d561312b565b8360051b60206132e6818301613230565b8681529185019181810190368411156132fe57600080fd5b865b848110156133d4578035868111156133185760008081fd5b8801606036829003121561332c5760008081fd5b61333461320e565b61333d82612c15565b815261334a86830161298a565b86820152604080830135898111156133625760008081fd5b9290920191601f36818501126133785760008081fd5b83358a81111561338a5761338a61312b565b61339b818301601f19168a01613230565b915080825236898287010111156133b25760008081fd5b808986018a840137600090820189015290820152845250918301918301613300565b50979650505050505050565b600080858511156133f057600080fd5b838611156133fd57600080fd5b5050820193919092039150565b6000845161341c818460208901612a3a565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600061107f602083018486613432565b80820180821115610c6f57610c6f613292565b60006020828403121561349457600080fd5b5051919050565b8082028115828204841417610c6f57610c6f613292565b6000826134cf57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160f01b031981358181169160028510156134fc5780818660020360031b1b83161692505b505092915050565b84815263ffffffff8416602082015260606040820152600061352a606083018486613432565b9695505050505050565b6000808335601e1984360301811261354b57600080fd5b8301803591506001600160401b0382111561356557600080fd5b6020019150368190038213156126d757600080fd5b6040815263ffffffff8351166040820152602083015160608201526000604084015160a060808401526135b060e0840182612a5e565b90506060850151603f198483030160a08501526135cd8282612a5e565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b60006040828403121561360557600080fd5b61360d6131e6565b9050815181526020820151602082015292915050565b60006040828403121561363557600080fd5b61161883836135f3565b60006080828403121561365157600080fd5b61365961320e565b82518152602083015161366b81612d2d565b602082015261367d84604085016135f3565b60408201529392505050565b634e487b7160e01b600052603260045260246000fd5b601f821115611e64576000816000526020600020601f850160051c810160208610156136c85750805b601f850160051c820191505b818110156136e7578281556001016136d4565b505050505050565b81516001600160401b038111156137085761370861312b565b61371c81613716845461315e565b8461369f565b602080601f83116001811461375157600084156137395750858301515b600019600386901b1c1916600185901b1785556136e7565b600085815260208120601f198616915b8281101561378057888601518255948401946001909101908401613761565b508582101561379e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101561382b57888303603f190185528151805163ffffffff1684528781015161ffff1688850152860151606087850181905261381781860183612a5e565b9689019694505050908601906001016137d7565b509098975050505050505050565b6001600160c01b031981358181169160088510156134fc5760089490940360031b84901b1690921692915050565b80356020831015610c6f57600019602084900360031b1b1692915050565b60006020828403121561389757600080fd5b8151611618816129bc565b600082516138b4818460208701612a3a565b919091019291505056fea26469706673582212208547624a0a909d348a728eed1538dc88ab8d9ef751ef14e2cc43c00622d4d99964736f6c63430008160033000000000000000000000000000000000000000000000000000000000000759e00000000000000000000000000000000000000000000000000000000000075ad0000000000000000000000000000000000000000000000000000000000007595000000000000000000000000000000000000000000000000000000000000768700000000000000000000000000000000000000000000000000000000000076d400000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e0000000000000000000000001a44076050125825900e736c501f859c50fe728c00000000000000000000000045813da61888a9908938f40604a87eab8e608447
Deployed Bytecode
0x6080604052600436106102935760003560e01c806382413eac1161015a578063bb0b6a53116100c1578063e5328e061161007a578063e5328e06146108b0578063ed9445d4146108c5578063f2fde38b146108e5578063f368ce2114610905578063fc0c546a14610939578063ff7bd03d1461096c57600080fd5b8063bb0b6a53146107ec578063bc70b35414610819578063c7c7f5b314610839578063ca5eb5e11461085a578063dbad31d61461087a578063e1a452181461089a57600080fd5b80639de36096116101135780639de36096146107505780639f68b96414610765578063a363b94514610779578063ad3b1b4714610799578063b98bd070146107b9578063b9e5567c146107d957600080fd5b806382413eac14610679578063826f1fb1146106a9578063857749b0146106c95780638da5cb5b146106e55780639ce704ee146107035780639d1580b41461072357600080fd5b80633b6f743b116101fe57806361d488af116101b757806361d488af146105ab5780636c0c85df146105c0578063715018a6146105e057806376a499f0146105f55780637b1e22c11461060a5780637d25a05e1461063e57600080fd5b80633b6f743b146104a557806342bdf044146104d257806354ddfe22146104f25780635535d461146105265780635e280f111461055357806360b71d4e1461058757600080fd5b806324a9d8531161025057806324a9d8531461036e57806325996dae1461039c5780632868f841146103e557806332e4e363146104195780633400288b1461045157806336ec8a221461047157600080fd5b8063023b1fc9146102985780630c7636aa146102ba5780630d35b415146102da57806313137d6514610312578063156a0d0f1461032557806317442b701461034c575b600080fd5b3480156102a457600080fd5b506102b86102b33660046129a1565b61098c565b005b3480156102c657600080fd5b506102b86102d53660046129d1565b610a10565b3480156102e657600080fd5b506102fa6102f5366004612a06565b610a66565b60405161030993929190612a8a565b60405180910390f35b6102b8610320366004612b76565b610b2a565b34801561033157600080fd5b506040805162b9270b60e21b81526000602082015201610309565b34801561035857600080fd5b5060408051600181526002602082015201610309565b34801561037a57600080fd5b506007546103899061ffff1681565b60405161ffff9091168152602001610309565b3480156103a857600080fd5b506103d07f000000000000000000000000000000000000000000000000000000000000759581565b60405163ffffffff9091168152602001610309565b3480156103f157600080fd5b506103d07f000000000000000000000000000000000000000000000000000000000000759e81565b34801561042557600080fd5b50600554610439906001600160a01b031681565b6040516001600160a01b039091168152602001610309565b34801561045d57600080fd5b506102b861046c366004612c29565b610be5565b34801561047d57600080fd5b506103d07f000000000000000000000000000000000000000000000000000000000000768781565b3480156104b157600080fd5b506104c56104c0366004612c61565b610bfb565b6040516103099190612cb2565b3480156104de57600080fd5b506102b86104ed366004612cc9565b610c75565b3480156104fe57600080fd5b506103d07f00000000000000000000000000000000000000000000000000000000000076d481565b34801561053257600080fd5b50610546610541366004612ce7565b610e4a565b6040516103099190612d1a565b34801561055f57600080fd5b506104397f0000000000000000000000001a44076050125825900e736c501f859c50fe728c81565b34801561059357600080fd5b5061059d60065481565b604051908152602001610309565b3480156105b757600080fd5b50610389600281565b3480156105cc57600080fd5b506104c56105db366004612d42565b610eef565b3480156105ec57600080fd5b506102b861105e565b34801561060157600080fd5b50610389600381565b34801561061657600080fd5b506103d07f00000000000000000000000000000000000000000000000000000000000075ad81565b34801561064a57600080fd5b50610661610659366004612c29565b600092915050565b6040516001600160401b039091168152602001610309565b34801561068557600080fd5b50610699610694366004612e06565b611072565b6040519015158152602001610309565b3480156106b557600080fd5b506102b86106c43660046129d1565b611087565b3480156106d557600080fd5b5060405160068152602001610309565b3480156106f157600080fd5b506000546001600160a01b0316610439565b610716610711366004612e7e565b6110dd565b6040516103099190612f73565b34801561072f57600080fd5b5061059d61073e366004612f81565b60036020526000908152604090205481565b34801561075c57600080fd5b50610389600181565b34801561077157600080fd5b506001610699565b34801561078557600080fd5b506102b8610794366004612f9c565b6112d3565b3480156107a557600080fd5b506102b86107b4366004612cc9565b611362565b3480156107c557600080fd5b506102b86107d4366004612fb5565b611505565b6107166107e7366004613029565b61151f565b3480156107f857600080fd5b5061059d610807366004612f81565b60016020526000908152604090205481565b34801561082557600080fd5b5061054661083436600461308b565b61161f565b61084c610847366004613029565b6117c7565b6040516103099291906130eb565b34801561086657600080fd5b506102b86108753660046129d1565b61194d565b34801561088657600080fd5b506104c5610895366004612c61565b6119d3565b3480156108a657600080fd5b5061038961271081565b3480156108bc57600080fd5b5061059d611a3a565b3480156108d157600080fd5b50600454610439906001600160a01b031681565b3480156108f157600080fd5b506102b86109003660046129d1565b611ad8565b34801561091157600080fd5b506103d07f00000000000000000000000000000000000000000000000000000000000075ad81565b34801561094557600080fd5b507f00000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e610439565b34801561097857600080fd5b5061069961098736600461310f565b611b16565b610994611b4c565b61271061ffff8216106109c557604051632b0caee160e01b815261ffff821660048201526024015b60405180910390fd5b6007805461ffff191661ffff83169081179091556040519081527f9bcf94806ecd549c5fde16e51a1aa08969f40766e486082ffa0776f594ceeba0906020015b60405180910390a150565b610a18611b4c565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f77dc8c64df705e1cadda346c392c907893d3513bc4cf95865b2ca90b793a78de90602001610a05565b60408051808201909152600080825260208201526060610a99604051806040016040528060008152602001600081525090565b60408051808201825260008082526001600160401b03602080840182905284518381529081019094529195509182610af4565b604080518082019091526000815260606020820152815260200190600190039081610acc5790505b509350600080610b0c88604001358960600135611b79565b60408051808201909152918252602082015296989597505050505050565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b03163314610b75576040516391ac5e4f60e01b81523360048201526024016109bc565b60208701803590610b8f90610b8a908a612f81565b611be0565b14610bcd57610ba16020880188612f81565b60405163309afaf360e21b815263ffffffff9091166004820152602088013560248201526044016109bc565b610bdc87878787878787611c1c565b50505050505050565b610bed611b4c565b610bf78282611dc9565b5050565b60408051808201909152600080825260208201526000610c2384604001358560600135611b79565b9150610c3d9050610c376020860186612f81565b82611e17565b600080610c4c60028785611e69565b9092509050610c69610c616020880188612f81565b838388611f31565b93505050505b92915050565b6004546001600160a01b03163314801590610c9b57506000546001600160a01b03163314155b15610cb95760405163f24eb55560e01b815260040160405180910390fd5b610ce37f00000000000000000000000000000000000000000000000000000000000075ad82612009565b7f00000000000000000000000000000000000000000000000000000000000076d463ffffffff167f00000000000000000000000000000000000000000000000000000000000075ad63ffffffff1603610dcf5760405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390527f00000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e169063a9059cbb906044016020604051808303816000875af1158015610da5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc99190613141565b50610e03565b610e036001600160a01b037f00000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e168383612081565b604080516001600160a01b0384168152602081018390527fb553c27b290d117801add9bfe5b9c82655aaa3f3b1ff88f04e8062e53985429a91015b60405180910390a15050565b600260209081526000928352604080842090915290825290208054610e6e9061315e565b80601f0160208091040260200160405190810160405280929190818152602001828054610e9a9061315e565b8015610ee75780601f10610ebc57610100808354040283529160200191610ee7565b820191906000526020600020905b815481529060010190602001808311610eca57829003601f168201915b505050505081565b6040805180820190915260008082526020820152610f367f000000000000000000000000000000000000000000000000000000000000759e8a6001600160401b0316611e17565b610f697f00000000000000000000000000000000000000000000000000000000000075ad896001600160401b0316611e17565b610f9c7f0000000000000000000000000000000000000000000000000000000000007595886001600160401b0316611e17565b610fcf7f0000000000000000000000000000000000000000000000000000000000007687876001600160401b0316611e17565b6110027f00000000000000000000000000000000000000000000000000000000000076d4866001600160401b0316611e17565b600060038a8a8a8a8a60405160200161102096959493929190613192565b604051602081830303815290604052905060006110408c6003888861161f565b905061104e8c838387611f31565b9c9b505050505050505050505050565b611066611b4c565b61107060006120e0565b565b6001600160a01b03811630145b949350505050565b61108f611b4c565b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f5767d79cd17d7554509a4dd59a5a7a9175c7e36466455d7b2fa478822880857990602001610a05565b6110e5612943565b6005546001600160a01b031633146111105760405163061af57960e01b815260040160405180910390fd5b6111437f000000000000000000000000000000000000000000000000000000000000759e8a6001600160401b0316612009565b6111767f00000000000000000000000000000000000000000000000000000000000075ad896001600160401b0316612009565b6111a97f0000000000000000000000000000000000000000000000000000000000007595886001600160401b0316612009565b6111dc7f0000000000000000000000000000000000000000000000000000000000007687876001600160401b0316612009565b61120f7f00000000000000000000000000000000000000000000000000000000000076d4866001600160401b0316612009565b600060038a8a8a8a8a60405160200161122d96959493929190613192565b6040516020818303038152906040529050600061124d8c6003888861161f565b6040805163ffffffff8f1681526001600160401b038e811660208301528d8116828401528c811660608301528b811660808301528a1660a082015290519192507f39d01394877aa469089f52f91bc8ff4d57872b2ccf0dfeecd086051d1e973bee919081900360c00190a161104e8c83836112cd36899003890189613260565b33612130565b6113086001600160a01b037f00000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e1633308461223b565b6113327f00000000000000000000000000000000000000000000000000000000000075ad8261227a565b6040518181527f54ff32c5fe6e04031abcc9d0c05fb2c146df6f5aad45f3d7d06f1e21c9f6bbfb90602001610a05565b61136a611b4c565b60065481111561138d57604051637806a4f560e11b815260040160405180910390fd5b806006600082825461139f91906132a8565b925050819055507f00000000000000000000000000000000000000000000000000000000000076d463ffffffff167f00000000000000000000000000000000000000000000000000000000000075ad63ffffffff16036114925760405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390527f00000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e169063a9059cbb906044016020604051808303816000875af1158015611468573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148c9190613141565b506114c6565b6114c66001600160a01b037f00000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e168383612081565b604080516001600160a01b0384168152602081018390527fc0819c13be868895eb93e40eaceb96de976442fa1d404e5c55f14bb65a8c489a9101610e3e565b61150d611b4c565b610bf761151a82846132bb565b6122ae565b611527612943565b6004546001600160a01b0316331480159061154d57506000546001600160a01b03163314155b1561156b5760405163f24eb55560e01b815260040160405180910390fd5b61158561157b6020860186612f81565b8560600135612009565b6000806115986001878860600135611e69565b90925090507fc67a11a48e2fbc72ed25165a3c32149b773e5ff8d498ec24615f4b47d66f839c6115cb6020880188612f81565b6040805163ffffffff9092168252606089013560208301520160405180910390a16116136115fc6020880188612f81565b838361160d368a90038a018a613260565b88612130565b925050505b9392505050565b63ffffffff8416600090815260026020908152604080832061ffff871684529091528120805460609291906116539061315e565b80601f016020809104026020016040519081016040528092919081815260200182805461167f9061315e565b80156116cc5780601f106116a1576101008083540402835291602001916116cc565b820191906000526020600020905b8154815290600101906020018083116116af57829003601f168201915b50505050509050805160000361171c5783838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092945061107f9350505050565b600083900361172c57905061107f565b600283106117aa5761177384848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506123b592505050565b8061178184600281886133e0565b6040516020016117939392919061340a565b60405160208183030381529060405291505061107f565b8383604051639a6d49cd60e01b81526004016109bc92919061345b565b6117cf612943565b60408051808201909152600080825260208201526000806117f887604001358860600135611b79565b90925090506118326001600160a01b037f00000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e1633308561223b565b6118486118426020890189612f81565b82612009565b6118727f00000000000000000000000000000000000000000000000000000000000075ad8261227a565b61187c81836132a8565b6006600082825461188d919061346f565b9091555060009050806118a260028a85611e69565b90925090506118ce6118b760208b018b612f81565b83836118c8368d90038d018d613260565b8b612130565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a9061191c908d018d612f81565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b611955611b4c565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c169063ca5eb5e190602401600060405180830381600087803b1580156119b857600080fd5b505af11580156119cc573d6000803e3d6000fd5b5050505050565b6040805180820190915260008082526020820152611a016119f76020850185612f81565b8460600135611e17565b600080611a146001868760600135611e69565b9092509050611a31611a296020870187612f81565b838387611f31565b95945050505050565b6006546040516370a0823160e01b8152306004820152600091906001600160a01b037f00000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e16906370a0823190602401602060405180830381865afa158015611aa5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac99190613482565b611ad391906132a8565b905090565b611ae0611b4c565b6001600160a01b038116611b0a57604051631e4fbdf760e01b8152600060048201526024016109bc565b611b13816120e0565b50565b6000602082018035906001908390611b2e9086612f81565b63ffffffff1681526020810191909152604001600020541492915050565b6000546001600160a01b031633146110705760405163118cdaa760e01b81523360048201526024016109bc565b6007548290600090819061271090611b959061ffff168561349b565b611b9f91906134b2565b9050611bab81846132a8565b915083821015611bd8576040516371c4efed60e01b815260048101839052602481018590526044016109bc565b509250929050565b63ffffffff811660009081526001602052604081205480610c6f5760405163f6ff4fb760e01b815263ffffffff841660048201526024016109bc565b6000611c2b60028287896133e0565b611c34916134d4565b60f01c90506002198101611c9a57611c4c86866123e1565b7f3db8474102b857712fc19a9142f559c0b9c2dd375fa0c50626bfa44eab47480187611c7b60208b018b612f81565b8888604051611c8d9493929190613504565b60405180910390a1611dbf565b60011961ffff821601611d1757600080611cb48888612576565b90925090506001600160a01b038216897fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c611cf260208e018e612f81565b6040805163ffffffff9092168252602082018690520160405180910390a35050611dbf565b60001961ffff821601611da057600080611d318888612576565b90925090507f3f42e057866db95fa13dd768aa8e103200d6ac6e7af2d51fff21fc32dc0be69489611d6560208d018d612f81565b6040805192835263ffffffff90911660208301526001600160a01b038516908201526060810183905260800160405180910390a15050611dbf565b60405163a7ac386360e01b815261ffff821660048201526024016109bc565b5050505050505050565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b9101610e3e565b63ffffffff821660009081526003602052604090205481811015611e645760405163735f7cd760e01b815263ffffffff8416600482015260248101829052604481018390526064016109bc565b505050565b60608082600003611e8d5760405163162908e360e11b815260040160405180910390fd5b6000611e9c60a0860186613534565b90501115611ebd57604051630b45411560e11b815260040160405180910390fd5b6040516001600160f01b031960f087901b1660208281019190915285013560228201526001600160c01b031960c085901b166042820152604a0160408051601f198184030181529190529150611f27611f196020860186612f81565b866108346080880188613534565b9050935093915050565b60408051808201909152600080825260208201527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611f9489611be0565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611fc992919061357a565b6040805180830381865afa158015611fe5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a319190613623565b8015610bf75763ffffffff82166000908152600360205260409020548181101561205c5760405163735f7cd760e01b815263ffffffff8416600482015260248101829052604481018390526064016109bc565b61206682826132a8565b63ffffffff8416600090815260036020526040902055505050565b6040516001600160a01b03838116602483015260448201839052611e6491859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506126de565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612138612943565b60006121478460000151612741565b602085015190915015612161576121618460200151612769565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016121b18c611be0565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b81526004016121ed92919061357a565b60806040518083038185885af115801561220b573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612230919061363f565b979650505050505050565b6040516001600160a01b0384811660248301528381166044830152606482018390526122749186918216906323b872dd906084016120ae565b50505050565b8015610bf75763ffffffff8216600090815260036020526040812080548392906122a590849061346f565b90915550505050565b60005b8151811015612385576122e08282815181106122cf576122cf613689565b6020026020010151604001516123b5565b8181815181106122f2576122f2613689565b6020026020010151604001516002600084848151811061231457612314613689565b60200260200101516000015163ffffffff1663ffffffff168152602001908152602001600020600084848151811061234e5761234e613689565b60200260200101516020015161ffff1661ffff168152602001908152602001600020908161237c91906136ef565b506001016122b1565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610a0591906137ae565b600281015161ffff8116600314610bf75781604051639a6d49cd60e01b81526004016109bc9190612d1a565b60006123f1600a600284866133e0565b6123fa91613839565b60c01c9050600061240f6012600a85876133e0565b61241891613839565b60c01c9050600061242d601a601286886133e0565b61243691613839565b60c01c9050600061244b6022601a87896133e0565b61245491613839565b60c01c90506000612469602a6022888a6133e0565b61247291613839565b60c01c90506124aa7f000000000000000000000000000000000000000000000000000000000000759e866001600160401b031661227a565b6124dd7f00000000000000000000000000000000000000000000000000000000000075ad856001600160401b031661227a565b6125107f0000000000000000000000000000000000000000000000000000000000007595846001600160401b031661227a565b6125437f0000000000000000000000000000000000000000000000000000000000007687836001600160401b031661227a565b610bdc7f00000000000000000000000000000000000000000000000000000000000076d4826001600160401b031661227a565b6000806125876022600285876133e0565b61259091613867565b91506125a0602a602285876133e0565b6125a991613839565b60c01c6001600160401b031690507f00000000000000000000000000000000000000000000000000000000000076d463ffffffff167f00000000000000000000000000000000000000000000000000000000000075ad63ffffffff16036126a35760405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390527f00000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e169063a9059cbb906044016020604051808303816000875af1158015612679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269d9190613141565b506126d7565b6126d76001600160a01b037f00000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e168383612081565b9250929050565b60006126f36001600160a01b0384168361284b565b905080516000141580156127185750808060200190518101906127169190613141565b155b15611e6457604051635274afe760e01b81526001600160a01b03841660048201526024016109bc565b6000813414612765576040516304fb820960e51b81523460048201526024016109bc565b5090565b60007f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ed9190613885565b90506001600160a01b038116612816576040516329b99a9560e11b815260040160405180910390fd5b610bf76001600160a01b038216337f0000000000000000000000001a44076050125825900e736c501f859c50fe728c8561223b565b60606116188383600084600080856001600160a01b0316848660405161287191906138a2565b60006040518083038185875af1925050503d80600081146128ae576040519150601f19603f3d011682016040523d82523d6000602084013e6128b3565b606091505b50915091506116138683836060826128d3576128ce8261291a565b611618565b81511580156128ea57506001600160a01b0384163b155b1561291357604051639996b31560e01b81526001600160a01b03851660048201526024016109bc565b5080611618565b80511561292a5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60405180606001604052806000801916815260200160006001600160401b03168152602001612985604051806040016040528060008152602001600081525090565b905290565b803561ffff8116811461299c57600080fd5b919050565b6000602082840312156129b357600080fd5b6116188261298a565b6001600160a01b0381168114611b1357600080fd5b6000602082840312156129e357600080fd5b8135611618816129bc565b600060e08284031215612a0057600080fd5b50919050565b600060208284031215612a1857600080fd5b81356001600160401b03811115612a2e57600080fd5b61107f848285016129ee565b60005b83811015612a55578181015183820152602001612a3d565b50506000910152565b60008151808452612a76816020860160208601612a3a565b601f01601f19169290920160200192915050565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b83811015612b055788870360bf19018552815180518852830151838801879052612af287890182612a5e565b9750509382019390820190600101612ac6565b5050875160608801525050506020850151608085015250905061107f565b600060608284031215612a0057600080fd5b60008083601f840112612b4757600080fd5b5081356001600160401b03811115612b5e57600080fd5b6020830191508360208285010111156126d757600080fd5b600080600080600080600060e0888a031215612b9157600080fd5b612b9b8989612b23565b96506060880135955060808801356001600160401b0380821115612bbe57600080fd5b612bca8b838c01612b35565b909750955060a08a01359150612bdf826129bc565b90935060c08901359080821115612bf557600080fd5b50612c028a828b01612b35565b989b979a50959850939692959293505050565b803563ffffffff8116811461299c57600080fd5b60008060408385031215612c3c57600080fd5b612c4583612c15565b946020939093013593505050565b8015158114611b1357600080fd5b60008060408385031215612c7457600080fd5b82356001600160401b03811115612c8a57600080fd5b612c96858286016129ee565b9250506020830135612ca781612c53565b809150509250929050565b815181526020808301519082015260408101610c6f565b60008060408385031215612cdc57600080fd5b8235612c45816129bc565b60008060408385031215612cfa57600080fd5b612d0383612c15565b9150612d116020840161298a565b90509250929050565b6020815260006116186020830184612a5e565b6001600160401b0381168114611b1357600080fd5b60008060008060008060008060006101008a8c031215612d6157600080fd5b612d6a8a612c15565b985060208a0135612d7a81612d2d565b975060408a0135612d8a81612d2d565b965060608a0135612d9a81612d2d565b955060808a0135612daa81612d2d565b945060a08a0135612dba81612d2d565b935060c08a01356001600160401b03811115612dd557600080fd5b612de18c828d01612b35565b90945092505060e08a0135612df581612c53565b809150509295985092959850929598565b60008060008060a08587031215612e1c57600080fd5b612e268686612b23565b935060608501356001600160401b03811115612e4157600080fd5b612e4d87828801612b35565b9094509250506080850135612e61816129bc565b939692955090935050565b600060408284031215612a0057600080fd5b60008060008060008060008060006101208a8c031215612e9d57600080fd5b612ea68a612c15565b985060208a0135612eb681612d2d565b975060408a0135612ec681612d2d565b965060608a0135612ed681612d2d565b955060808a0135612ee681612d2d565b945060a08a0135612ef681612d2d565b935060c08a01356001600160401b03811115612f1157600080fd5b612f1d8c828d01612b35565b9094509250612f3190508b60e08c01612e6c565b90509295985092959850929598565b805182526001600160401b0360208201511660208301526040810151611e64604084018280518252602090810151910152565b60808101610c6f8284612f40565b600060208284031215612f9357600080fd5b61161882612c15565b600060208284031215612fae57600080fd5b5035919050565b60008060208385031215612fc857600080fd5b82356001600160401b0380821115612fdf57600080fd5b818501915085601f830112612ff357600080fd5b81358181111561300257600080fd5b8660208260051b850101111561301757600080fd5b60209290920196919550909350505050565b60008060006080848603121561303e57600080fd5b83356001600160401b0381111561305457600080fd5b613060868287016129ee565b9350506130708560208601612e6c565b91506060840135613080816129bc565b809150509250925092565b600080600080606085870312156130a157600080fd5b6130aa85612c15565b93506130b86020860161298a565b925060408501356001600160401b038111156130d357600080fd5b6130df87828801612b35565b95989497509550505050565b60c081016130f98285612f40565b82516080830152602083015160a0830152611618565b60006060828403121561312157600080fd5b6116188383612b23565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561315357600080fd5b815161161881612c53565b600181811c9082168061317257607f821691505b602082108103612a0057634e487b7160e01b600052602260045260246000fd5b60f09690961b6001600160f01b031916865260c094851b6001600160c01b0319908116600288015293851b8416600a87015291841b83166012860152831b8216601a85015290911b166022820152602a0190565b604080519081016001600160401b03811182821017156132085761320861312b565b60405290565b604051606081016001600160401b03811182821017156132085761320861312b565b604051601f8201601f191681016001600160401b03811182821017156132585761325861312b565b604052919050565b60006040828403121561327257600080fd5b61327a6131e6565b82358152602083013560208201528091505092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c6f57610c6f613292565b60006001600160401b03808411156132d5576132d561312b565b8360051b60206132e6818301613230565b8681529185019181810190368411156132fe57600080fd5b865b848110156133d4578035868111156133185760008081fd5b8801606036829003121561332c5760008081fd5b61333461320e565b61333d82612c15565b815261334a86830161298a565b86820152604080830135898111156133625760008081fd5b9290920191601f36818501126133785760008081fd5b83358a81111561338a5761338a61312b565b61339b818301601f19168a01613230565b915080825236898287010111156133b25760008081fd5b808986018a840137600090820189015290820152845250918301918301613300565b50979650505050505050565b600080858511156133f057600080fd5b838611156133fd57600080fd5b5050820193919092039150565b6000845161341c818460208901612a3a565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600061107f602083018486613432565b80820180821115610c6f57610c6f613292565b60006020828403121561349457600080fd5b5051919050565b8082028115828204841417610c6f57610c6f613292565b6000826134cf57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160f01b031981358181169160028510156134fc5780818660020360031b1b83161692505b505092915050565b84815263ffffffff8416602082015260606040820152600061352a606083018486613432565b9695505050505050565b6000808335601e1984360301811261354b57600080fd5b8301803591506001600160401b0382111561356557600080fd5b6020019150368190038213156126d757600080fd5b6040815263ffffffff8351166040820152602083015160608201526000604084015160a060808401526135b060e0840182612a5e565b90506060850151603f198483030160a08501526135cd8282612a5e565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b60006040828403121561360557600080fd5b61360d6131e6565b9050815181526020820151602082015292915050565b60006040828403121561363557600080fd5b61161883836135f3565b60006080828403121561365157600080fd5b61365961320e565b82518152602083015161366b81612d2d565b602082015261367d84604085016135f3565b60408201529392505050565b634e487b7160e01b600052603260045260246000fd5b601f821115611e64576000816000526020600020601f850160051c810160208610156136c85750805b601f850160051c820191505b818110156136e7578281556001016136d4565b505050505050565b81516001600160401b038111156137085761370861312b565b61371c81613716845461315e565b8461369f565b602080601f83116001811461375157600084156137395750858301515b600019600386901b1c1916600185901b1785556136e7565b600085815260208120601f198616915b8281101561378057888601518255948401946001909101908401613761565b508582101561379e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101561382b57888303603f190185528151805163ffffffff1684528781015161ffff1688850152860151606087850181905261381781860183612a5e565b9689019694505050908601906001016137d7565b509098975050505050505050565b6001600160c01b031981358181169160088510156134fc5760089490940360031b84901b1690921692915050565b80356020831015610c6f57600019602084900360031b1b1692915050565b60006020828403121561389757600080fd5b8151611618816129bc565b600082516138b4818460208701612a3a565b919091019291505056fea26469706673582212208547624a0a909d348a728eed1538dc88ab8d9ef751ef14e2cc43c00622d4d99964736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000759e00000000000000000000000000000000000000000000000000000000000075ad0000000000000000000000000000000000000000000000000000000000007595000000000000000000000000000000000000000000000000000000000000768700000000000000000000000000000000000000000000000000000000000076d400000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e0000000000000000000000001a44076050125825900e736c501f859c50fe728c00000000000000000000000045813da61888a9908938f40604a87eab8e608447
-----Decoded View---------------
Arg [0] : _arbitrumEid (uint32): 30110
Arg [1] : _celoEid (uint32): 30125
Arg [2] : _ethEid (uint32): 30101
Arg [3] : _tonEid (uint32): 30343
Arg [4] : _tronEid (uint32): 30420
Arg [5] : _token (address): 0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e
Arg [6] : _lzEndpoint (address): 0x1a44076050125825900e736c501f859c50fE728c
Arg [7] : _delegate (address): 0x45813DA61888a9908938f40604a87EAB8E608447
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000000000000000000000000759e
Arg [1] : 00000000000000000000000000000000000000000000000000000000000075ad
Arg [2] : 0000000000000000000000000000000000000000000000000000000000007595
Arg [3] : 0000000000000000000000000000000000000000000000000000000000007687
Arg [4] : 00000000000000000000000000000000000000000000000000000000000076d4
Arg [5] : 00000000000000000000000048065fbbe25f71c9282ddf5e1cd6d6a887483d5e
Arg [6] : 0000000000000000000000001a44076050125825900e736c501f859c50fe728c
Arg [7] : 00000000000000000000000045813da61888a9908938f40604a87eab8e608447
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.