Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 67 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw Fee | 23575330 | 168 days ago | IN | 0 ETH | 0.00008228 | ||||
| Execute302 | 23490099 | 180 days ago | IN | 0 ETH | 0.00021671 | ||||
| Commit Verificat... | 23490094 | 180 days ago | IN | 0 ETH | 0.00004603 | ||||
| Execute302 | 23490013 | 180 days ago | IN | 0 ETH | 0.0000634 | ||||
| Commit Verificat... | 23490009 | 180 days ago | IN | 0 ETH | 0.00005432 | ||||
| Execute302 | 23475469 | 182 days ago | IN | 0 ETH | 0.00014777 | ||||
| Commit Verificat... | 23475468 | 182 days ago | IN | 0 ETH | 0.00012526 | ||||
| Withdraw Fee | 23410218 | 191 days ago | IN | 0 ETH | 0.0000517 | ||||
| Execute302 | 23395269 | 193 days ago | IN | 0 ETH | 0.00009206 | ||||
| Commit Verificat... | 23395267 | 193 days ago | IN | 0 ETH | 0.00002036 | ||||
| Execute302 | 23390291 | 194 days ago | IN | 0 ETH | 0.00158857 | ||||
| Commit Verificat... | 23390288 | 194 days ago | IN | 0 ETH | 0.0003381 | ||||
| Execute302 | 23390284 | 194 days ago | IN | 0 ETH | 0.00157647 | ||||
| Commit Verificat... | 23390281 | 194 days ago | IN | 0 ETH | 0.00031912 | ||||
| Execute302 | 23383263 | 195 days ago | IN | 0 ETH | 0.00008467 | ||||
| Commit Verificat... | 23383262 | 195 days ago | IN | 0 ETH | 0.00007009 | ||||
| Execute302 | 23383261 | 195 days ago | IN | 0 ETH | 0.00007935 | ||||
| Commit Verificat... | 23383257 | 195 days ago | IN | 0 ETH | 0.00006621 | ||||
| Execute302 | 23383256 | 195 days ago | IN | 0 ETH | 0.00007814 | ||||
| Commit Verificat... | 23383255 | 195 days ago | IN | 0 ETH | 0.00006567 | ||||
| Execute302 | 23383249 | 195 days ago | IN | 0 ETH | 0.00007723 | ||||
| Commit Verificat... | 23383248 | 195 days ago | IN | 0 ETH | 0.00006621 | ||||
| Execute302 | 23382007 | 195 days ago | IN | 0 ETH | 0.00016158 | ||||
| Commit Verificat... | 23382003 | 195 days ago | IN | 0 ETH | 0.00003166 | ||||
| Execute302 | 23381272 | 195 days ago | IN | 0 ETH | 0.00003705 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Executor
Compiler Version
v0.8.30+commit.73712a01
Optimization Enabled:
Yes with 400 runs
Other Settings:
prague EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: LZBL-1.2
// copied and modified from https://github.com/LayerZero-Labs/LayerZero-v2/blob/main/packages/layerzero-v2/evm/messagelib/contracts/Executor.sol
pragma solidity ^0.8.24;
import {IExecutor} from "@layerzerolabs/lz-evm-messagelib-v2/contracts/interfaces/IExecutor.sol";
import {IExecutorFeeLib} from "@layerzerolabs/lz-evm-messagelib-v2/contracts/interfaces/IExecutorFeeLib.sol";
import {IReceiveUlnE2} from "@layerzerolabs/lz-evm-messagelib-v2/contracts/uln/interfaces/IReceiveUlnE2.sol";
import {Origin, ILayerZeroEndpointV2} from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import {PacketV1Codec} from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {ILayerZeroEndpointV2Extended} from "./interfaces/ILayerZeroEndpointV2Extended.sol";
import {IReceiveUlnView, VerificationState, ExecutionState} from "./interfaces/ILayerZeroReceiveUlnView.sol";
import {Worker} from "./Worker.sol";
/// @title Executor Contract.
/// @notice Executes LayerZero V2 operations and handles the job fee logic for messaging libraries.
/// @dev Extends `Worker`, `ReentrancyGuard`, and implements `IExecutor`.
contract Executor is Worker, ReentrancyGuard, IExecutor {
using PacketV1Codec for bytes;
/// @dev Represents an empty payload hash.
bytes32 public constant EMPTY_PAYLOAD_HASH = bytes32(0);
/// @dev Represents a nil (max value) payload hash.
bytes32 public constant NIL_PAYLOAD_HASH = bytes32(type(uint256).max);
/// @dev Configuration per destination endpoint ID.
mapping(uint32 dstEid => DstConfig) public dstConfig;
/// @dev LayerZero V2 endpoint address.
address public immutable ENDPOINT;
/// @dev Local endpoint ID for LayerZero V2.
uint32 public immutable LOCAL_EID_V2;
/// @dev LayerZero V2 ReceiveUln302 contract address.
address public immutable RECEIVE_ULN302;
/// @dev Error thrown when `commitVerification` is called with an invalid state (i.e. Packet not verifiable).
error Executor_InvalidVerificationState();
/**
* @dev Initializes the Executor contract with endpoint, ULN302, admin, and libraries.
* @param _endpoint Address of LayerZeroV2 endpoint contract.
* @param _receiveUln302 LayerZeroV2 RecieveUln302 contract address to commit verifications.
* @param _messageLibs Addresses of messaging fee libraries allowed for job assignment.
* @param _priceFeed Address of price feed contract used for fee calculations.
* @param _roleAdmin Address assigned `DEFAULT_ADMIN_ROLE`.
* @param _admins Additional addresses to be granted `ADMIN_ROLE`.
*/
constructor(
address _endpoint,
address _receiveUln302,
address[] memory _messageLibs,
address _priceFeed,
address _roleAdmin,
address[] memory _admins
)
Worker(_messageLibs, _priceFeed, 12000, _roleAdmin, _admins)
notZeroAddress(_endpoint)
notZeroAddress(_receiveUln302)
{
ENDPOINT = _endpoint;
LOCAL_EID_V2 = ILayerZeroEndpointV2Extended(_endpoint).eid();
RECEIVE_ULN302 = _receiveUln302;
}
/**
* @dev Sets configuration parameters for multiple destination EIDs.
* This function allows `ADMIN_ROLE` to set various parameters for each destination EID.
* It updates the `dstConfig` mapping with new values for each destination EID.
* @param _params Array of the `DstConfigParam` structs containing destination settings.
* Emits a `DstConfigSet` event with the updated parameters.
*/
function setDstConfig(DstConfigParam[] calldata _params) external onlyRole(_ADMIN_ROLE) {
uint256 paramsLength = _params.length;
for (uint256 i = 0; i < paramsLength; ++i) {
// Write each destination config into the mapping, overwriting any previous value.
DstConfigParam memory param = _params[i];
dstConfig[param.dstEid] = DstConfig(
param.lzReceiveBaseGas,
param.multiplierBps,
param.floorMarginUSD,
param.nativeCap,
param.lzComposeBaseGas
);
}
emit DstConfigSet(_params);
}
/**
* @dev Sends native tokens to specified addresses on the target chain.
* It can only be called by an address with `ADMIN_ROLE` and is protected against reentrancy attacks.
* @param _origin Origin information for the message context.
* @param _dstEid Destination endpoint EID where native tokens should be dropped.
* @param _oapp Address of the target OApp contract on the destination chain.
* @param _nativeDropParams Array of `NativeDropParams` specifying receivers and amounts.
* @param _nativeDropGasLimit Gas limit for each native transfer call.
*/
function nativeDrop(
Origin calldata _origin,
uint32 _dstEid,
address _oapp,
NativeDropParams[] calldata _nativeDropParams,
uint256 _nativeDropGasLimit
) external payable onlyRole(_ADMIN_ROLE) nonReentrant {
// Internal call ensures an event is emitted and the total amount spent is tracked.
_nativeDrop(_origin, _dstEid, _oapp, _nativeDropParams, _nativeDropGasLimit);
}
/**
* @dev Commits a packet verification to the `ReceiveUln302` contract.
* It checks the verification state of the packet header and payload hash.
* If the packet is in a verifiable state, it commits the verification.
* If the packet is in a verifying state, it reverts with a `LzExecutor_Verifying` error.
* @param _packetHeader Encoded packet header bytes.
* @param _payloadHash Keccak256 hash of the packet payload.
*/
function commitVerification(
bytes calldata _packetHeader,
bytes32 _payloadHash
) external nonReentrant {
VerificationState verificationState = verifiable(_packetHeader, _payloadHash);
if (verificationState == VerificationState.Verifiable) {
// Verification passed, commit to the verifier contract.
IReceiveUlnE2(RECEIVE_ULN302).commitVerification(_packetHeader, _payloadHash);
} else {
// Revert if a Packet is still verifying or not verifiable.
revert Executor_InvalidVerificationState();
}
}
/**
* @notice Executes LayerZero V2 receive logic (`lzReceive`).
* @dev This function is used to execute messages received from LayerZero V2.
* It wraps the call in a try/catch block to handle any errors that may occur.
* @param _executionParams Struct containing `origin`, `receiver`, `guid`, `message`, `extraData`, and `gasLimit`.
*/
function execute302(ExecutionParams calldata _executionParams) external payable nonReentrant {
try
ILayerZeroEndpointV2Extended(ENDPOINT).lzReceive{
value: msg.value,
gas: _executionParams.gasLimit
}(
_executionParams.origin,
_executionParams.receiver,
_executionParams.guid,
_executionParams.message,
_executionParams.extraData
)
// solhint-disable-next-line no-empty-blocks
{
// Do nothing.
} catch (bytes memory reason) {
// On error, call the alert method on the endpoint for logging.
ILayerZeroEndpointV2Extended(ENDPOINT).lzReceiveAlert(
_executionParams.origin,
_executionParams.receiver,
_executionParams.guid,
_executionParams.gasLimit,
msg.value,
_executionParams.message,
_executionParams.extraData,
reason
);
}
}
/**
* @notice Composes LayerZero V2 packets (lzCompose).
* @dev This function is used to compose messages for LayerZero V2.
* It wraps the call in a try/catch block to handle any errors that may occur.
* @param _from Address from which the message originates.
* @param _to Address to which the message is destined.
* @param _guid Unique GUID for this message.
* @param _index Sequence index for multi-packet messages.
* @param _message Payload to send.
* @param _extraData Additional data for the endpoint.
* @param _gasLimit Gas limit provided for lzCompose.
*/
function compose302(
address _from,
address _to,
bytes32 _guid,
uint16 _index,
bytes calldata _message,
bytes calldata _extraData,
uint256 _gasLimit
) external payable nonReentrant {
try
ILayerZeroEndpointV2Extended(ENDPOINT).lzCompose{value: msg.value, gas: _gasLimit}(
_from,
_to,
_guid,
_index,
_message,
_extraData
)
// solhint-disable-next-line no-empty-blocks
{
// Do nothing.
} catch (bytes memory reason) {
ILayerZeroEndpointV2Extended(ENDPOINT).lzComposeAlert(
_from,
_to,
_guid,
_index,
_gasLimit,
msg.value,
_message,
_extraData,
reason
);
}
}
/**
* @dev Executes a native drop then LayerZero V2 receive logic in a single transaction.
* This function allows for a native drop to be performed before executing the LayerZero V2 receive logic.
* It combines the native drop and lzReceive into a single transaction to save on gas
* and ensure atomicity of the operations.
* This function can only be called by an address with ADMIN_ROLE and is protected against reentrancy attacks.
* @param _nativeDropParams Array of `NativeDropParams` for native drop.
* @param _nativeDropGasLimit Gas limit for each native transfer.
* @param _executionParams Struct containing parameters for `lzReceive`.
*/
function nativeDropAndExecute302(
NativeDropParams[] calldata _nativeDropParams,
uint256 _nativeDropGasLimit,
ExecutionParams calldata _executionParams
) external payable onlyRole(_ADMIN_ROLE) nonReentrant {
// Spend as much of `msg.value` as needed for drops; leftover is used for receive.
uint256 spent = _nativeDrop(
_executionParams.origin,
LOCAL_EID_V2,
_executionParams.receiver,
_nativeDropParams,
_nativeDropGasLimit
);
// Only remaining value is used for the receive call.
uint256 value = msg.value - spent;
try
ILayerZeroEndpointV2Extended(ENDPOINT).lzReceive{
value: value,
gas: _executionParams.gasLimit
}(
_executionParams.origin,
_executionParams.receiver,
_executionParams.guid,
_executionParams.message,
_executionParams.extraData
)
// solhint-disable-next-line no-empty-blocks
{
// Do nothing.
} catch (bytes memory reason) {
// If the receive fails, report for monitoring.
ILayerZeroEndpointV2Extended(ENDPOINT).lzReceiveAlert(
_executionParams.origin,
_executionParams.receiver,
_executionParams.guid,
_executionParams.gasLimit,
value,
_executionParams.message,
_executionParams.extraData,
reason
);
}
}
// --- Message Lib ---
/**
* @dev Assigns a job to the Executor and calculates the fee. Used by message libraries.
* @param _dstEid Destination EID.
* @param _sender Address sending the job.
* @param _calldataSize Size of calldata in bytes.
* @param _options Additional options as bytes.
* @return fee Fee calculated for the job.
*/
function assignJob(
uint32 _dstEid,
address _sender,
uint256 _calldataSize,
bytes calldata _options
) external onlyRole(_MESSAGE_LIB_ROLE) onlyAcl(_sender) whenNotPaused returns (uint256 fee) {
// Construct fee parameters for the fee library call.
IExecutorFeeLib.FeeParams memory params = IExecutorFeeLib.FeeParams(
priceFeed,
_dstEid,
_sender,
_calldataSize,
defaultMultiplierBps
);
// Call external fee library (pluggable) for fee computation.
fee = IExecutorFeeLib(workerFeeLib).getFeeOnSend(params, dstConfig[_dstEid], _options);
}
/**
* @dev Assigns a job for CmdLib (`destination = localEidV2`).
* @param _sender Address sending the job.
* @param _options Additional options as bytes.
* @return fee Fee calculated for the job.
*/
function assignJob(
address _sender,
bytes calldata _options
) external onlyRole(_MESSAGE_LIB_ROLE) onlyAcl(_sender) whenNotPaused returns (uint256 fee) {
// Construct fee parameters for the fee library call.
IExecutorFeeLib.FeeParamsForRead memory params = IExecutorFeeLib.FeeParamsForRead(
priceFeed,
_sender,
defaultMultiplierBps
);
// Call external fee library (pluggable) for fee computation.
fee = IExecutorFeeLib(workerFeeLib).getFeeOnSend(params, dstConfig[LOCAL_EID_V2], _options);
}
/**
* @dev Returns the current execution state for a packet.
* @param _packetHeader Encoded packet header.
* @param _payloadHash Hash of the packet payload.
* @return ExecutionState Current execution state of the packet.
*/
function executable(
bytes calldata _packetHeader,
bytes32 _payloadHash
) public view returns (ExecutionState) {
// Decode the receiver and origin details from the header.
address _receiver = _packetHeader.receiverB20();
Origin memory _origin = Origin(
_packetHeader.srcEid(),
_packetHeader.sender(),
_packetHeader.nonce()
);
// Query the payload hash stored in the endpoint for the packet.
bytes32 payloadHash = ILayerZeroEndpointV2(ENDPOINT).inboundPayloadHash(
_receiver,
_origin.srcEid,
_origin.sender,
_origin.nonce
);
// 1. Already executed if the payload hash has been cleared and the nonce is less than or equal to `lazyInboundNonce`.
if (
payloadHash == EMPTY_PAYLOAD_HASH &&
_origin.nonce <=
ILayerZeroEndpointV2(ENDPOINT).lazyInboundNonce(
_receiver,
_origin.srcEid,
_origin.sender
)
) {
return ExecutionState.Executed;
}
// 2. Executable: if nonce has not been executed and has not been nilified and nonce is less than or equal to `inboundNonce`.
if (
payloadHash != NIL_PAYLOAD_HASH &&
payloadHash == _payloadHash &&
_origin.nonce <=
ILayerZeroEndpointV2(ENDPOINT).inboundNonce(_receiver, _origin.srcEid, _origin.sender)
) {
return ExecutionState.Executable;
}
// 3. Pending but verified: only start active executable polling if payload hash is not empty nor `nil`.
if (payloadHash != EMPTY_PAYLOAD_HASH && payloadHash != NIL_PAYLOAD_HASH) {
return ExecutionState.VerifiedButNotExecutable;
}
// 4. Not executable: `catch-all`.
return ExecutionState.NotExecutable;
}
/**
* @dev Checks if a packet is in a verifiable state.
* @param _packetHeader Encoded packet header bytes.
* @param _payloadHash Keccak256 hash of packet payload.
* @return state Current `VerificationState` of the packet.
*/
function verifiable(
bytes calldata _packetHeader,
bytes32 _payloadHash
) public view returns (VerificationState) {
// Assert the header is valid for the local endpoint ID.
IReceiveUlnView(RECEIVE_ULN302).assertHeader(_packetHeader, LOCAL_EID_V2);
// Decode the receiver and origin details from the header.
address receiver = _packetHeader.receiverB20();
Origin memory origin = Origin(
_packetHeader.srcEid(),
_packetHeader.sender(),
_packetHeader.nonce()
);
// 1. Endpoint must support initialization (config present, etc).
if (!_initializable(origin, receiver)) {
return VerificationState.NotInitializable;
}
// 2. Endpoint verifiable (e.g. not already verified).
if (!_endpointVerifiable(origin, receiver, _payloadHash)) {
return VerificationState.Verified;
}
// 3. ULN verifiable (DVN or ULN, packet is verifiable).
if (
IReceiveUlnView(RECEIVE_ULN302).verifiable(
IReceiveUlnView(RECEIVE_ULN302).getUlnConfig(receiver, origin.srcEid),
keccak256(_packetHeader),
_payloadHash
)
) {
return VerificationState.Verifiable;
}
// 4. Still verifying.
return VerificationState.Verifying;
}
// --- Only ACL ---
/**
* @dev Returns the fee for a given destination and calldata size (for `msg.sender`).
* @param _dstEid Destination EID.
* @param _sender Address of message sender.
* @param _calldataSize Calldata size.
* @param _options Options encoded as bytes.
* @return fee Quoted fee for the job.
*/
function getFee(
uint32 _dstEid,
address _sender,
uint256 _calldataSize,
bytes calldata _options
) external view onlyAcl(_sender) whenNotPaused returns (uint256 fee) {
// Construct fee parameters for the fee library call.
IExecutorFeeLib.FeeParams memory params = IExecutorFeeLib.FeeParams(
priceFeed,
_dstEid,
_sender,
_calldataSize,
defaultMultiplierBps
);
// Call external fee library (pluggable) for fee computation.
fee = IExecutorFeeLib(workerFeeLib).getFee(params, dstConfig[_dstEid], _options);
}
/**
* @dev Returns the fee for a read job (for `CmdLib`, `msg.sender`).
* @param _sender Address of message sender.
* @param _options Options encoded as bytes.
* @return fee Quoted fee for the job.
*/
function getFee(
address _sender,
bytes calldata _options
) external view onlyAcl(_sender) whenNotPaused returns (uint256 fee) {
// Construct fee parameters for the fee library call.
IExecutorFeeLib.FeeParamsForRead memory params = IExecutorFeeLib.FeeParamsForRead(
priceFeed,
_sender,
defaultMultiplierBps
);
// Call external fee library (pluggable) for fee computation.
fee = IExecutorFeeLib(workerFeeLib).getFee(params, dstConfig[LOCAL_EID_V2], _options);
}
/// @dev Internal function to distribute native tokens to multiple recipients.
/// @param _origin Origin information for the message context.
/// @param _dstEid Destination endpoint ID.
/// @param _oapp Target contract on remote chain.
/// @param _nativeDropParams Array of receivers and amounts.
/// @param _nativeDropGasLimit Gas limit for each transfer call.
/// @return spent Total amount of native tokens sent.
function _nativeDrop(
Origin calldata _origin,
uint32 _dstEid,
address _oapp,
NativeDropParams[] calldata _nativeDropParams,
uint256 _nativeDropGasLimit
) internal returns (uint256 spent) {
uint256 paramsLength = _nativeDropParams.length;
bool[] memory success = new bool[](paramsLength);
for (uint256 i = 0; i < paramsLength; ++i) {
NativeDropParams memory param = _nativeDropParams[i];
// slither-disable-next-line arbitrary-send-eth,low-level-calls,return-bomb
(bool sent, ) = param.receiver.call{value: param.amount, gas: _nativeDropGasLimit}("");
success[i] = sent;
spent += param.amount;
}
emit NativeDropApplied(_origin, _dstEid, _oapp, _nativeDropParams, success);
}
/// @dev Checks whether the endpoint can be verified and the payload hash is not already stored.
/// @param _origin Origin information for the message context.
/// @param _receiver Address of the endpoint’s receiver contract.
/// @param _payloadHash Keccak256 hash of the message payload.
/// @return boolean `True` if the endpoint is verifiable and hasn’t seen this payload before.
function _endpointVerifiable(
Origin memory _origin,
address _receiver,
bytes32 _payloadHash
) internal view returns (bool) {
// check endpoint verifiable
if (!_verifiable(_origin, _receiver, RECEIVE_ULN302, _payloadHash)) return false;
// if `endpoint.verifiable`, also check if the payload hash matches
// the endpoint that allows re-verification. Check if this payload has already been verified.
if (
ILayerZeroEndpointV2(ENDPOINT).inboundPayloadHash(
_receiver,
_origin.srcEid,
_origin.sender,
_origin.nonce
) == _payloadHash
) return false;
return true;
}
/**
* @dev Internal helper to verify library and endpoint readiness.
* Checks if the receive library is valid for the receiver,
* if the endpoint is verifiable for the origin and receiver,
* and if the payload hash is non‐zero.
* @param _origin Origin context for verification.
* @param _receiver Receiver address on this chain.
* @param _receiveLib Address of the ULN receive library to check.
* @param _payloadHash Payload hash that must be non‐zero.
* @return True if the receive library is registered, the endpoint is verifiable, and `payloadHash ≠ 0`.
*/
function _verifiable(
Origin memory _origin,
address _receiver,
address _receiveLib,
bytes32 _payloadHash
) internal view returns (bool) {
// Library must be a valid receive library for this endpoint.
if (
!ILayerZeroEndpointV2(ENDPOINT).isValidReceiveLibrary(
_receiver,
_origin.srcEid,
_receiveLib
)
) return false;
// Endpoint must report itself as verifiable for this origin.
if (!ILayerZeroEndpointV2(ENDPOINT).verifiable(_origin, _receiver)) return false;
// Reject zero‐value hashes (not a real message).
if (_payloadHash == EMPTY_PAYLOAD_HASH) return false;
return true;
}
/**
* @dev Checks if the endpoint supports initialization for a given origin and receiver.
* @param _origin Origin context to query.
* @param _receiver Address of the receiver contract to check.
* @return boolean `True` if the endpoint supports initialization for this origin and receiver.
*/
function _initializable(Origin memory _origin, address _receiver) internal view returns (bool) {
try ILayerZeroEndpointV2(ENDPOINT).initializable(_origin, _receiver) returns (
bool initializable
) {
return initializable;
} catch {
return false;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { IWorker } from "./IWorker.sol";
import { ILayerZeroExecutor } from "./ILayerZeroExecutor.sol";
import { ILayerZeroReadExecutor } from "./ILayerZeroReadExecutor.sol";
interface IExecutor is IWorker, ILayerZeroExecutor, ILayerZeroReadExecutor {
struct DstConfigParam {
uint32 dstEid;
uint64 lzReceiveBaseGas;
uint64 lzComposeBaseGas;
uint16 multiplierBps;
uint128 floorMarginUSD;
uint128 nativeCap;
}
struct DstConfig {
uint64 lzReceiveBaseGas;
uint16 multiplierBps;
uint128 floorMarginUSD; // uses priceFeed PRICE_RATIO_DENOMINATOR
uint128 nativeCap;
uint64 lzComposeBaseGas;
}
struct ExecutionParams {
address receiver;
Origin origin;
bytes32 guid;
bytes message;
bytes extraData;
uint256 gasLimit;
}
struct NativeDropParams {
address receiver;
uint256 amount;
}
event DstConfigSet(DstConfigParam[] params);
event NativeDropApplied(Origin origin, uint32 dstEid, address oapp, NativeDropParams[] params, bool[] success);
function dstConfig(uint32 _dstEid) external view returns (uint64, uint16, uint128, uint128, uint64);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { IExecutor } from "./IExecutor.sol";
interface IExecutorFeeLib {
struct FeeParams {
address priceFeed;
uint32 dstEid;
address sender;
uint256 calldataSize;
uint16 defaultMultiplierBps;
}
struct FeeParamsForRead {
address priceFeed;
address sender;
uint16 defaultMultiplierBps;
}
error Executor_NoOptions();
error Executor_NativeAmountExceedsCap(uint256 amount, uint256 cap);
error Executor_UnsupportedOptionType(uint8 optionType);
error Executor_InvalidExecutorOptions(uint256 cursor);
error Executor_ZeroLzReceiveGasProvided();
error Executor_ZeroLzComposeGasProvided();
error Executor_ZeroCalldataSizeProvided();
error Executor_EidNotSupported(uint32 eid);
function getFeeOnSend(
FeeParams calldata _params,
IExecutor.DstConfig calldata _dstConfig,
bytes calldata _options
) external returns (uint256 fee);
function getFee(
FeeParams calldata _params,
IExecutor.DstConfig calldata _dstConfig,
bytes calldata _options
) external view returns (uint256 fee);
function getFeeOnSend(
FeeParamsForRead calldata _params,
IExecutor.DstConfig calldata _dstConfig,
bytes calldata _options
) external returns (uint256 fee);
function getFee(
FeeParamsForRead calldata _params,
IExecutor.DstConfig calldata _dstConfig,
bytes calldata _options
) external view returns (uint256 fee);
function version() external view returns (uint64 major, uint8 minor);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface ILayerZeroExecutor {
// @notice query price and assign jobs at the same time
// @param _dstEid - the destination endpoint identifier
// @param _sender - the source sending contract address. executors may apply price discrimination to senders
// @param _calldataSize - dynamic data size of message + caller params
// @param _options - optional parameters for extra service plugins, e.g. sending dust tokens at the destination chain
function assignJob(
uint32 _dstEid,
address _sender,
uint256 _calldataSize,
bytes calldata _options
) external returns (uint256 price);
// @notice query the executor price for relaying the payload and its proof to the destination chain
// @param _dstEid - the destination endpoint identifier
// @param _sender - the source sending contract address. executors may apply price discrimination to senders
// @param _calldataSize - dynamic data size of message + caller params
// @param _options - optional parameters for extra service plugins, e.g. sending dust tokens at the destination chain
function getFee(
uint32 _dstEid,
address _sender,
uint256 _calldataSize,
bytes calldata _options
) external view returns (uint256 price);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface ILayerZeroReadExecutor {
// @notice query price and assign jobs at the same time
// @param _sender - the source sending contract address. executors may apply price discrimination to senders
// @param _options - optional parameters for extra service plugins, e.g. sending dust tokens at the destination chain
function assignJob(address _sender, bytes calldata _options) external returns (uint256 fee);
// @notice query the executor price for executing the payload on this chain
// @param _sender - the source sending contract address. executors may apply price discrimination to senders
// @param _options - optional parameters for extra service plugins, e.g. sending dust tokens
function getFee(address _sender, bytes calldata _options) external view returns (uint256 fee);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IWorker {
event SetWorkerLib(address workerLib);
event SetPriceFeed(address priceFeed);
event SetDefaultMultiplierBps(uint16 multiplierBps);
event SetSupportedOptionTypes(uint32 dstEid, uint8[] optionTypes);
event Withdraw(address lib, address to, uint256 amount);
error Worker_NotAllowed();
error Worker_OnlyMessageLib();
error Worker_RoleRenouncingDisabled();
function setPriceFeed(address _priceFeed) external;
function priceFeed() external view returns (address);
function setDefaultMultiplierBps(uint16 _multiplierBps) external;
function defaultMultiplierBps() external view returns (uint16);
function withdrawFee(address _lib, address _to, uint256 _amount) external;
function setSupportedOptionTypes(uint32 _eid, uint8[] calldata _optionTypes) external;
function getSupportedOptionTypes(uint32 _eid) external view returns (uint8[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
/// @dev should be implemented by the ReceiveUln302 contract and future ReceiveUln contracts on EndpointV2
interface IReceiveUlnE2 {
/// @notice for each dvn to verify the payload
/// @dev this function signature 0x0223536e
function verify(bytes calldata _packetHeader, bytes32 _payloadHash, uint64 _confirmations) external;
/// @notice verify the payload at endpoint, will check if all DVNs verified
function commitVerification(bytes calldata _packetHeader, bytes32 _payloadHash) external;
}// 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 { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import { SetConfigParam } from "./IMessageLibManager.sol";
enum MessageLibType {
Send,
Receive,
SendAndReceive
}
interface IMessageLib is IERC165 {
function setConfig(address _oapp, SetConfigParam[] calldata _config) external;
function getConfig(uint32 _eid, address _oapp, uint32 _configType) external view returns (bytes memory config);
function isSupportedEid(uint32 _eid) external view returns (bool);
// message libs of same major version are compatible
function version() external view returns (uint64 major, uint8 minor, uint8 endpointVersion);
function messageLibType() external view returns (MessageLibType);
}// 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
pragma solidity >=0.8.0;
import { MessagingFee } from "./ILayerZeroEndpointV2.sol";
import { IMessageLib } from "./IMessageLib.sol";
struct Packet {
uint64 nonce;
uint32 srcEid;
address sender;
uint32 dstEid;
bytes32 receiver;
bytes32 guid;
bytes message;
}
interface ISendLib is IMessageLib {
function send(
Packet calldata _packet,
bytes calldata _options,
bool _payInLzToken
) external returns (MessagingFee memory, bytes memory encodedPacket);
function quote(
Packet calldata _packet,
bytes calldata _options,
bool _payInLzToken
) external view returns (MessagingFee memory);
function setTreasury(address _treasury) external;
function withdrawFee(address _to, uint256 _amount) external;
function withdrawLzTokenFee(address _lzToken, address _to, uint256 _amount) external;
}// SPDX-License-Identifier: LZBL-1.2
pragma solidity ^0.8.20;
library AddressCast {
error AddressCast_InvalidSizeForAddress();
error AddressCast_InvalidAddress();
function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) {
if (_addressBytes.length > 32) revert AddressCast_InvalidAddress();
result = bytes32(_addressBytes);
unchecked {
uint256 offset = 32 - _addressBytes.length;
result = result >> (offset * 8);
}
}
function toBytes32(address _address) internal pure returns (bytes32 result) {
result = bytes32(uint256(uint160(_address)));
}
function toBytes(bytes32 _addressBytes32, uint256 _size) internal pure returns (bytes memory result) {
if (_size == 0 || _size > 32) revert AddressCast_InvalidSizeForAddress();
result = new bytes(_size);
unchecked {
uint256 offset = 256 - _size * 8;
assembly {
mstore(add(result, 32), shl(offset, _addressBytes32))
}
}
}
function toAddress(bytes32 _addressBytes32) internal pure returns (address result) {
result = address(uint160(uint256(_addressBytes32)));
}
function toAddress(bytes calldata _addressBytes) internal pure returns (address result) {
if (_addressBytes.length != 20) revert AddressCast_InvalidAddress();
result = address(bytes20(_addressBytes));
}
}// SPDX-License-Identifier: LZBL-1.2
pragma solidity ^0.8.20;
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
library Transfer {
using SafeERC20 for IERC20;
address internal constant ADDRESS_ZERO = address(0);
error Transfer_NativeFailed(address _to, uint256 _value);
error Transfer_ToAddressIsZero();
function native(address _to, uint256 _value) internal {
if (_to == ADDRESS_ZERO) revert Transfer_ToAddressIsZero();
(bool success, ) = _to.call{ value: _value }("");
if (!success) revert Transfer_NativeFailed(_to, _value);
}
function token(address _token, address _to, uint256 _value) internal {
if (_to == ADDRESS_ZERO) revert Transfer_ToAddressIsZero();
IERC20(_token).safeTransfer(_to, _value);
}
function nativeOrToken(address _token, address _to, uint256 _value) internal {
if (_token == ADDRESS_ZERO) {
native(_to, _value);
} else {
token(_token, _to, _value);
}
}
}// SPDX-License-Identifier: LZBL-1.2
pragma solidity ^0.8.20;
import { Packet } from "../../interfaces/ISendLib.sol";
import { AddressCast } from "../../libs/AddressCast.sol";
library PacketV1Codec {
using AddressCast for address;
using AddressCast for bytes32;
uint8 internal constant PACKET_VERSION = 1;
// header (version + nonce + path)
// version
uint256 private constant PACKET_VERSION_OFFSET = 0;
// nonce
uint256 private constant NONCE_OFFSET = 1;
// path
uint256 private constant SRC_EID_OFFSET = 9;
uint256 private constant SENDER_OFFSET = 13;
uint256 private constant DST_EID_OFFSET = 45;
uint256 private constant RECEIVER_OFFSET = 49;
// payload (guid + message)
uint256 private constant GUID_OFFSET = 81; // keccak256(nonce + path)
uint256 private constant MESSAGE_OFFSET = 113;
function encode(Packet memory _packet) internal pure returns (bytes memory encodedPacket) {
encodedPacket = abi.encodePacked(
PACKET_VERSION,
_packet.nonce,
_packet.srcEid,
_packet.sender.toBytes32(),
_packet.dstEid,
_packet.receiver,
_packet.guid,
_packet.message
);
}
function encodePacketHeader(Packet memory _packet) internal pure returns (bytes memory) {
return
abi.encodePacked(
PACKET_VERSION,
_packet.nonce,
_packet.srcEid,
_packet.sender.toBytes32(),
_packet.dstEid,
_packet.receiver
);
}
function encodePayload(Packet memory _packet) internal pure returns (bytes memory) {
return abi.encodePacked(_packet.guid, _packet.message);
}
function header(bytes calldata _packet) internal pure returns (bytes calldata) {
return _packet[0:GUID_OFFSET];
}
function version(bytes calldata _packet) internal pure returns (uint8) {
return uint8(bytes1(_packet[PACKET_VERSION_OFFSET:NONCE_OFFSET]));
}
function nonce(bytes calldata _packet) internal pure returns (uint64) {
return uint64(bytes8(_packet[NONCE_OFFSET:SRC_EID_OFFSET]));
}
function srcEid(bytes calldata _packet) internal pure returns (uint32) {
return uint32(bytes4(_packet[SRC_EID_OFFSET:SENDER_OFFSET]));
}
function sender(bytes calldata _packet) internal pure returns (bytes32) {
return bytes32(_packet[SENDER_OFFSET:DST_EID_OFFSET]);
}
function senderAddressB20(bytes calldata _packet) internal pure returns (address) {
return sender(_packet).toAddress();
}
function dstEid(bytes calldata _packet) internal pure returns (uint32) {
return uint32(bytes4(_packet[DST_EID_OFFSET:RECEIVER_OFFSET]));
}
function receiver(bytes calldata _packet) internal pure returns (bytes32) {
return bytes32(_packet[RECEIVER_OFFSET:GUID_OFFSET]);
}
function receiverB20(bytes calldata _packet) internal pure returns (address) {
return receiver(_packet).toAddress();
}
function guid(bytes calldata _packet) internal pure returns (bytes32) {
return bytes32(_packet[GUID_OFFSET:MESSAGE_OFFSET]);
}
function message(bytes calldata _packet) internal pure returns (bytes calldata) {
return bytes(_packet[MESSAGE_OFFSET:]);
}
function payload(bytes calldata _packet) internal pure returns (bytes calldata) {
return bytes(_packet[GUID_OFFSET:]);
}
function payloadHash(bytes calldata _packet) internal pure returns (bytes32) {
return keccak256(payload(_packet));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {IERC165, ERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol)
pragma solidity >=0.8.4;
/**
* @dev External interface of AccessControl declared to support ERC-165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted to signal this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
* Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
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.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 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 {
/**
* @dev An operation with an ERC-20 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 Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(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.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
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.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
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.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
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 Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
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 {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
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 silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// 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: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
bool private _paused;
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-FileCopyrightText: 2025 Molecula <info@molecula.fi>
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.24;
import {ConstantsCoreV2} from "./../coreV2/Constants.sol";
/// @title ValueValidator.
/// @notice Contract for validating common value-based conditions.
/// @dev Provides modifiers to check for zero values, zero addresses, and `msg.value` conditions.
contract ValueValidator {
/// @dev Error: `msg.sender` is not authorized for this function.
error ENotAuthorized();
/// @dev Error thrown when a value is zero but must be non-zero.
error EZeroValue();
/// @dev Error thrown when an address is zero but must be non-zero.
error EZeroAddress();
/// @dev Error thrown when `msg.value` is not zero but must be zero.
error EMsgValueIsNotZero();
/// @dev Error: Provided array is empty.
error EEmptyArray();
/// @dev Error: Percentage is invalid.
error EInvalidPercentage();
/**
* @dev Ensures the function is called by the expected sender.
* @param expectedSender Address that is allowed to call the function.
* @custom:revert ENotAuthorized Check if the caller is not the expected sender.
*/
modifier only(address expectedSender) {
if (msg.sender != expectedSender) {
revert ENotAuthorized();
}
_;
}
/// @dev Modifier that checks if a value is not zero.
/// @param value Value to check.
modifier notZero(uint256 value) {
// slither-disable-next-line incorrect-equality
if (value == 0) {
revert EZeroValue();
}
_;
}
/// @dev Modifier that checks if an address is not zero.
/// @param addr Address to check.
modifier notZeroAddress(address addr) {
if (addr == address(0)) {
revert EZeroAddress();
}
_;
}
/// @dev Modifier that ensures `msg.value` is zero.
modifier zeroMsgValue() {
if (msg.value != 0) {
revert EMsgValueIsNotZero();
}
_;
}
/// @dev Modifier that checks if the array is empty.
/// @param arrayLength Array length to check.
modifier notEmpty(uint256 arrayLength) {
if (arrayLength == 0) {
revert EEmptyArray();
}
_;
}
/// @dev Modifier that validates if the basis points value is within the valid range (0-10000).
/// @param bps Basis points value to validate.
/// @custom:revert EInvalidPercentage Check if bps exceeds the maximum allowed value (10000).
modifier checkBPS(uint16 bps) {
if (bps > ConstantsCoreV2.PERCENTAGE_FACTOR) {
revert EInvalidPercentage();
}
_;
}
}// SPDX-FileCopyrightText: 2025 Molecula <info@molecula.fi>
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.24;
/// @title ConstantsCoreV2.
/// @notice Library containing core constants used across the protocol.
/// @dev Contains immutable values that are frequently used in other contracts.
library ConstantsCoreV2 {
/// @notice Special address used to represent the native token (e.g., ETH) according to EIP-7528:
/// https://eips.ethereum.org/EIPS/eip-7528
/// @dev This pseudo-address is commonly used to differentiate between ERC20 tokens and the native tokens.
address public constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev Basis points factor, where 100% = 10,000.
/// Used as a denominator in percentage calculations.
uint16 public constant PERCENTAGE_FACTOR = 10_000;
}// SPDX-License-Identifier: LZBL-1.2
// copied from https://github.com/LayerZero-Labs/LayerZero-v2/blob/main/packages/layerzero-v2/evm/messagelib/contracts/Executor.sol
pragma solidity ^0.8.24;
import {Origin} from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
/**
* @dev Extended interface for LayerZero Endpoint v2 for message processing, composing, and alerting.
*/
interface ILayerZeroEndpointV2Extended {
/**
* @dev Returns the endpoint ID (EID) for this contract.
* @return Endpoint EID (unique uint32 identifier)
*/
function eid() external view returns (uint32);
/**
* @notice Receives and processes a cross-chain message.
* @dev Called by Executor or LayerZero infrastructure to deliver a message.
* @param _origin Struct describing the source chain and sender.
* @param _receiver Destination receiver contract address.
* @param _guid Unique message GUID (32 bytes).
* @param _message Serialized message payload.
* @param _extraData Extra data (optional, may be empty).
*/
function lzReceive(
Origin calldata _origin,
address _receiver,
bytes32 _guid,
bytes calldata _message,
bytes calldata _extraData
) external payable;
/**
* @notice Alerts about a failed message delivery or execution attempt.
* @dev Used for off-chain monitoring and reprocessing flows.
* @param _origin Struct describing the source chain and sender.
* @param _receiver Destination receiver contract address.
* @param _guid Unique message GUID (32 bytes).
* @param _gas Gas provided for the failed attempt.
* @param _value Native token value sent.
* @param _message Serialized message payload.
* @param _extraData Extra data passed during the call.
* @param _reason ABI-encoded revert reason or error data.
*/
function lzReceiveAlert(
Origin calldata _origin,
address _receiver,
bytes32 _guid,
uint256 _gas,
uint256 _value,
bytes calldata _message,
bytes calldata _extraData,
bytes calldata _reason
) external;
/**
* @notice Composes (initiates) a new cross-chain message from one contract to another.
* @dev Used for multi-hop or chained message execution.
* @param _from Originating contract address.
* @param _to Destination contract address.
* @param _guid Unique message GUID.
* @param _index Message sequence index for ordering.
* @param _message Serialized payload.
* @param _extraData Extra data (optional, may be empty).
*/
function lzCompose(
address _from,
address _to,
bytes32 _guid,
uint16 _index,
bytes calldata _message,
bytes calldata _extraData
) external payable;
/**
* @notice Alerts about a failed compose attempt.
* @dev Used for off-chain monitoring and diagnostics.
* @param _from Originating contract address.
* @param _to Destination contract address.
* @param _guid Unique message GUID.
* @param _index Message sequence index.
* @param _gas Gas provided for the failed attempt.
* @param _value Native token value sent.
* @param _message Serialized payload.
* @param _extraData Extra data passed during the call.
* @param _reason ABI-encoded revert reason or error data.
*/
function lzComposeAlert(
address _from,
address _to,
bytes32 _guid,
uint16 _index,
uint256 _gas,
uint256 _value,
bytes calldata _message,
bytes calldata _extraData,
bytes calldata _reason
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title LayerZero ULN Verification and Execution State Enums & View Interface.
/// @dev These enums and interface are used for verifying and tracking LayerZero Ultra Light Node packet states.
/**
* @dev Represents the verification status of a LayerZero packet.
* - Verifying: Packet is still undergoing DVN verification.
* - Verifiable: Packet is ready to be committed after successful DVN verification.
* - Verified: Packet has been verified.
* - NotInitializable: Packet cannot be initialized for verification due to config/state.
*/
enum VerificationState {
Verifying,
Verifiable,
Verified,
NotInitializable
}
/**
* @dev Represents the execution status of a LayerZero packet.
* - NotExecutable: Packet cannot be executed (waiting for verification).
* - VerifiedButNotExecutable: Packet has been verified but is not yet executable (active polling).
* - Executable: Packet is executable (can be processed by the executor).
* - Executed: Packet has already been executed.
*/
enum ExecutionState {
NotExecutable,
VerifiedButNotExecutable,
Executable,
Executed
}
/**
* @dev Interface for reading Ultra Light Node (ULN) verification config and status.
*/
interface IReceiveUlnView {
/**
* @dev ULN DVN configuration for a given remote chain and OApp.
* @param confirmations Number of block confirmations required for DVN.
* @param requiredDVNCount Number of required DVNs (0 = default, special NIL_DVN_COUNT disables).
* @param optionalDVNCount Number of optional DVNs (0 = default, special NIL_DVN_COUNT disables).
* @param optionalDVNThreshold Minimum number of optional DVN confirmations required.
* @param requiredDVNs List of required DVN addresses (sorted, unique, may overlap with optional).
* @param optionalDVNs List of optional DVN addresses (sorted, unique, may overlap with required).
*/
struct UlnConfig {
uint64 confirmations;
uint8 requiredDVNCount;
uint8 optionalDVNCount;
uint8 optionalDVNThreshold;
address[] requiredDVNs;
address[] optionalDVNs;
}
/**
* @dev Checks if a packet is verifiable given its ULN config, header hash, and payload hash.
* @param _config ULN configuration to check against.
* @param _headerHash keccak256 hash of the packet header.
* @param _payloadHash keccak256 hash of the packet payload.
* @return True if the packet is currently verifiable.
*/
function verifiable(
UlnConfig memory _config,
bytes32 _headerHash,
bytes32 _payloadHash
) external view returns (bool);
/**
* @dev Returns the current ULN configuration for a given OApp and remote EID.
* @param _oapp Address of the OApp (on this chain).
* @param _remoteEid Remote LayerZero endpoint ID.
* @return rtnConfig Current ULN config for this OApp and remote endpoint.
*/
function getUlnConfig(
address _oapp,
uint32 _remoteEid
) external view returns (UlnConfig memory rtnConfig);
/**
* @dev Asserts that the provided packet header is valid for the local endpoint ID.
* @param _packetHeader Encoded packet header bytes.
* @param _localEid Local LayerZero endpoint ID.
*/
function assertHeader(bytes calldata _packetHeader, uint32 _localEid) external pure;
}// SPDX-License-Identifier: LZBL-1.2
// copied from https://github.com/LayerZero-Labs/LayerZero-v2/blob/main/packages/layerzero-v2/evm/messagelib/contracts/Worker.sol
pragma solidity ^0.8.24;
import {IWorker} from "@layerzerolabs/lz-evm-messagelib-v2/contracts/interfaces/IWorker.sol";
import {ISendLib} from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol";
import {Transfer} from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/Transfer.sol";
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";
import {ValueValidator} from "../common/ValueValidator.sol";
abstract contract Worker is AccessControl, Pausable, IWorker, ValueValidator {
/// @dev Role for contracts allowed to assign jobs (messaging libraries).
bytes32 internal constant _MESSAGE_LIB_ROLE = keccak256("MESSAGE_LIB_ROLE");
/// @dev Role representing addresses in the allowlist.
bytes32 internal constant _ALLOWLIST = keccak256("ALLOWLIST");
/// @dev Role representing addresses in the denylist.
bytes32 internal constant _DENYLIST = keccak256("DENYLIST");
/// @dev Admin role for configuration changes.
bytes32 internal constant _ADMIN_ROLE = keccak256("ADMIN_ROLE");
/// @dev Address of the ExecutorFeeLib contract used for fee computations.
address public workerFeeLib;
/// @dev Number of addresses currently in the allowlist.
uint64 public allowlistSize;
/// @dev Default multiplier (in basis points) applied to computed fees.
uint16 public defaultMultiplierBps;
/// @dev Address of the external price feed used by ExecutorFeeLib.
address public priceFeed;
/// @dev Mapping of remote LZ EIDs to supported option type codes.
mapping(uint32 eid => uint8[] optionTypes) internal _supportedOptionTypes;
// ========================= Constructor =========================
/**
* @dev Initialize Worker with initial libraries, admin, price feed, and roles.
* @param _messageLibs Array of message lib addresses that are granted the MESSAGE_LIB_ROLE.
* @param _priceFeed Price feed address (for fee quoting).
* @param _defaultMultiplierBps Default fee multiplier (bps).
* @param _roleAdmin Address that is granted the DEFAULT_ADMIN_ROLE (can grant and revoke all roles).
* @param _admins Array of admin addresses that are granted the ADMIN_ROLE.
*/
constructor(
address[] memory _messageLibs,
address _priceFeed,
uint16 _defaultMultiplierBps,
address _roleAdmin,
address[] memory _admins
) {
defaultMultiplierBps = _defaultMultiplierBps;
priceFeed = _priceFeed;
if (_roleAdmin != address(0x0)) {
// _roleAdmin can grant and revoke all roles
_grantRole(DEFAULT_ADMIN_ROLE, _roleAdmin);
}
// solhint-disable-next-line gas-length-in-loops
for (uint256 i = 0; i < _messageLibs.length; ++i) {
// Grant _MESSAGE_LIB_ROLE to all provided message libraries
_grantRole(_MESSAGE_LIB_ROLE, _messageLibs[i]);
}
// solhint-disable-next-line gas-length-in-loops
for (uint256 i = 0; i < _admins.length; ++i) {
// Grant _ADMIN_ROLE to all provided admin addresses
_grantRole(_ADMIN_ROLE, _admins[i]);
}
}
// ========================= Modifier =========================
/**
* @dev Modifier that restricts access to only those passing the ACL check.
* Can be used to guard fee queries, job assignments, etc.
* @param _sender Address to check ACL against.
*/
modifier onlyAcl(address _sender) {
if (!hasAcl(_sender)) {
revert Worker_NotAllowed();
}
_;
}
/**
* @dev Access control list logic.
* - If sender is in denylist: always denied
* - If allowlist is empty or sender is in allowlist: allowed
* - Else: denied
* @param _sender Address to check for ACL.
* @return True if allowed, false otherwise.
*/
function hasAcl(address _sender) public view returns (bool) {
if (hasRole(_DENYLIST, _sender)) {
return false;
} else if (allowlistSize == 0 || hasRole(_ALLOWLIST, _sender)) {
// If allowlist is empty (open mode) or sender is in allowlist
return true;
} else {
return false;
}
}
// ========================= OnyDefaultAdmin =========================
/**
* @dev Pauses or unpauses contract (if used with whenNotPaused).
* Only callable by DEFAULT_ADMIN_ROLE.
* @param _paused True to pause, false to unpause.
*/
function setPaused(bool _paused) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (_paused) {
_pause();
} else {
_unpause();
}
}
// ========================= OnlyAdmin =========================
/**
* @dev Updates the price feed contract used for fee calculation.
* Only callable by ADMIN_ROLE.
* @param _priceFeed New price feed address.
*/
function setPriceFeed(
address _priceFeed
) external onlyRole(_ADMIN_ROLE) notZeroAddress(_priceFeed) {
priceFeed = _priceFeed;
emit SetPriceFeed(_priceFeed);
}
/**
* @dev Updates ExecutorFeeLib address used for all fee calculations.
* Only callable by ADMIN_ROLE.
* @param _workerFeeLib Address of new ExecutorFeeLib contract.
*/
function setWorkerFeeLib(
address _workerFeeLib
) external onlyRole(_ADMIN_ROLE) notZeroAddress(_workerFeeLib) {
workerFeeLib = _workerFeeLib;
emit SetWorkerLib(_workerFeeLib);
}
/**
* @dev Updates the default fee multiplier (basis points).
* Only callable by ADMIN_ROLE.
* @param _multiplierBps New default multiplier (bps).
*/
function setDefaultMultiplierBps(uint16 _multiplierBps) external onlyRole(_ADMIN_ROLE) {
defaultMultiplierBps = _multiplierBps;
emit SetDefaultMultiplierBps(_multiplierBps);
}
/**
* @dev Withdraws protocol fees from supported message ULN libraries.
* Only callable by ADMIN_ROLE. Library must have MESSAGE_LIB_ROLE.
* @param _lib Message library address to withdraw from.
* @param _to Recipient address.
* @param _amount Amount to withdraw.
*/
function withdrawFee(
address _lib,
address _to,
uint256 _amount
) external onlyRole(_ADMIN_ROLE) {
if (!hasRole(_MESSAGE_LIB_ROLE, _lib)) revert Worker_OnlyMessageLib();
// Call withdrawFee on the underlying library
ISendLib(_lib).withdrawFee(_to, _amount);
emit Withdraw(_lib, _to, _amount);
}
/**
* @dev Withdraws ERC20 tokens or native currency.
* @param _token Token address (use address(0) for native).
* @param _to Recipient address.
* @param _amount Amount to withdraw.
*/
function withdrawToken(
address _token,
address _to,
uint256 _amount
) external onlyRole(_ADMIN_ROLE) {
// transfers native if _token is address(0x0)
Transfer.nativeOrToken(_token, _to, _amount);
}
/**
* @dev Set supported option type codes for a given remote endpoint.
* Used for feature upgrades, testing, or protocol extension.
* Only callable by ADMIN_ROLE.
* @param _eid Endpoint ID.
* @param _optionTypes List of supported option codes.
*/
function setSupportedOptionTypes(
uint32 _eid,
uint8[] calldata _optionTypes
) external onlyRole(_ADMIN_ROLE) {
_supportedOptionTypes[_eid] = _optionTypes;
}
// ========================= View Functions =========================
/**
* @dev Returns the list of supported option types for a given remote endpoint.
* @param _eid Endpoint ID.
* @return Array of option type codes.
*/
function getSupportedOptionTypes(uint32 _eid) external view returns (uint8[] memory) {
return _supportedOptionTypes[_eid];
}
// ========================= Internal Functions =========================
/**
* @dev Overrides AccessControl's _grantRole to increment allowlistSize as needed.
* @param _role Role to grant.
* @param _account Address to grant role to.
* @return True if role was granted, false otherwise.
*/
function _grantRole(bytes32 _role, address _account) internal override returns (bool) {
if (_role == _ALLOWLIST && !hasRole(_role, _account)) {
++allowlistSize;
}
return super._grantRole(_role, _account);
}
/**
* @dev Overrides AccessControl's _revokeRole to decrement allowlistSize as needed.
* @param _role Role to revoke.
* @param _account Address to revoke role from.
* @return True if role was revoked, false otherwise.
*/
function _revokeRole(bytes32 _role, address _account) internal override returns (bool) {
if (_role == _ALLOWLIST && hasRole(_role, _account)) {
--allowlistSize;
}
return super._revokeRole(_role, _account);
}
/**
* @dev Overrides AccessControl to disable renouncing of roles.
* Disable renouncing roles to prevent accidental loss of permissions.
*/
function renounceRole(bytes32 /*role*/, address /*account*/) public pure override {
revert Worker_RoleRenouncingDisabled();
}
}{
"evmVersion": "prague",
"optimizer": {
"enabled": true,
"runs": 400
},
"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":"address","name":"_endpoint","type":"address"},{"internalType":"address","name":"_receiveUln302","type":"address"},{"internalType":"address[]","name":"_messageLibs","type":"address[]"},{"internalType":"address","name":"_priceFeed","type":"address"},{"internalType":"address","name":"_roleAdmin","type":"address"},{"internalType":"address[]","name":"_admins","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"EEmptyArray","type":"error"},{"inputs":[],"name":"EInvalidPercentage","type":"error"},{"inputs":[],"name":"EMsgValueIsNotZero","type":"error"},{"inputs":[],"name":"ENotAuthorized","type":"error"},{"inputs":[],"name":"EZeroAddress","type":"error"},{"inputs":[],"name":"EZeroValue","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"Executor_InvalidVerificationState","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer_NativeFailed","type":"error"},{"inputs":[],"name":"Transfer_ToAddressIsZero","type":"error"},{"inputs":[],"name":"Worker_NotAllowed","type":"error"},{"inputs":[],"name":"Worker_OnlyMessageLib","type":"error"},{"inputs":[],"name":"Worker_RoleRenouncingDisabled","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"uint64","name":"lzReceiveBaseGas","type":"uint64"},{"internalType":"uint64","name":"lzComposeBaseGas","type":"uint64"},{"internalType":"uint16","name":"multiplierBps","type":"uint16"},{"internalType":"uint128","name":"floorMarginUSD","type":"uint128"},{"internalType":"uint128","name":"nativeCap","type":"uint128"}],"indexed":false,"internalType":"struct IExecutor.DstConfigParam[]","name":"params","type":"tuple[]"}],"name":"DstConfigSet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"indexed":false,"internalType":"struct Origin","name":"origin","type":"tuple"},{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":false,"internalType":"address","name":"oapp","type":"address"},{"components":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"indexed":false,"internalType":"struct IExecutor.NativeDropParams[]","name":"params","type":"tuple[]"},{"indexed":false,"internalType":"bool[]","name":"success","type":"bool[]"}],"name":"NativeDropApplied","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"multiplierBps","type":"uint16"}],"name":"SetDefaultMultiplierBps","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"priceFeed","type":"address"}],"name":"SetPriceFeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":false,"internalType":"uint8[]","name":"optionTypes","type":"uint8[]"}],"name":"SetSupportedOptionTypes","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"workerLib","type":"address"}],"name":"SetWorkerLib","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lib","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMPTY_PAYLOAD_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ENDPOINT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCAL_EID_V2","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NIL_PAYLOAD_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECEIVE_ULN302","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowlistSize","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"address","name":"_sender","type":"address"},{"internalType":"uint256","name":"_calldataSize","type":"uint256"},{"internalType":"bytes","name":"_options","type":"bytes"}],"name":"assignJob","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"bytes","name":"_options","type":"bytes"}],"name":"assignJob","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_packetHeader","type":"bytes"},{"internalType":"bytes32","name":"_payloadHash","type":"bytes32"}],"name":"commitVerification","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"uint16","name":"_index","type":"uint16"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"bytes","name":"_extraData","type":"bytes"},{"internalType":"uint256","name":"_gasLimit","type":"uint256"}],"name":"compose302","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"defaultMultiplierBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"dstEid","type":"uint32"}],"name":"dstConfig","outputs":[{"internalType":"uint64","name":"lzReceiveBaseGas","type":"uint64"},{"internalType":"uint16","name":"multiplierBps","type":"uint16"},{"internalType":"uint128","name":"floorMarginUSD","type":"uint128"},{"internalType":"uint128","name":"nativeCap","type":"uint128"},{"internalType":"uint64","name":"lzComposeBaseGas","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_packetHeader","type":"bytes"},{"internalType":"bytes32","name":"_payloadHash","type":"bytes32"}],"name":"executable","outputs":[{"internalType":"enum ExecutionState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"receiver","type":"address"},{"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":"bytes","name":"extraData","type":"bytes"},{"internalType":"uint256","name":"gasLimit","type":"uint256"}],"internalType":"struct IExecutor.ExecutionParams","name":"_executionParams","type":"tuple"}],"name":"execute302","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"address","name":"_sender","type":"address"},{"internalType":"uint256","name":"_calldataSize","type":"uint256"},{"internalType":"bytes","name":"_options","type":"bytes"}],"name":"getFee","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"bytes","name":"_options","type":"bytes"}],"name":"getFee","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"}],"name":"getSupportedOptionTypes","outputs":[{"internalType":"uint8[]","name":"","type":"uint8[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"}],"name":"hasAcl","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"address","name":"_oapp","type":"address"},{"components":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IExecutor.NativeDropParams[]","name":"_nativeDropParams","type":"tuple[]"},{"internalType":"uint256","name":"_nativeDropGasLimit","type":"uint256"}],"name":"nativeDrop","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IExecutor.NativeDropParams[]","name":"_nativeDropParams","type":"tuple[]"},{"internalType":"uint256","name":"_nativeDropGasLimit","type":"uint256"},{"components":[{"internalType":"address","name":"receiver","type":"address"},{"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":"bytes","name":"extraData","type":"bytes"},{"internalType":"uint256","name":"gasLimit","type":"uint256"}],"internalType":"struct IExecutor.ExecutionParams","name":"_executionParams","type":"tuple"}],"name":"nativeDropAndExecute302","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_multiplierBps","type":"uint16"}],"name":"setDefaultMultiplierBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"uint64","name":"lzReceiveBaseGas","type":"uint64"},{"internalType":"uint64","name":"lzComposeBaseGas","type":"uint64"},{"internalType":"uint16","name":"multiplierBps","type":"uint16"},{"internalType":"uint128","name":"floorMarginUSD","type":"uint128"},{"internalType":"uint128","name":"nativeCap","type":"uint128"}],"internalType":"struct IExecutor.DstConfigParam[]","name":"_params","type":"tuple[]"}],"name":"setDstConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_priceFeed","type":"address"}],"name":"setPriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"uint8[]","name":"_optionTypes","type":"uint8[]"}],"name":"setSupportedOptionTypes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_workerFeeLib","type":"address"}],"name":"setWorkerFeeLib","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_packetHeader","type":"bytes"},{"internalType":"bytes32","name":"_payloadHash","type":"bytes32"}],"name":"verifiable","outputs":[{"internalType":"enum VerificationState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_lib","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"workerFeeLib","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60e060405234801561000f575f5ffd5b5060405161425438038061425483398101604081905261002e9161043d565b6001805461ffff60e81b191661017760ed1b179055600280546001600160a01b0319166001600160a01b038581169190911790915584908490612ee09085908590821615610082576100805f83610217565b505b5f5b85518110156100df576100d67f724aface199fe5bed93ae8508474576a9adf3dc443b2c451842a2242919f19de8783815181106100c3576100c36104e1565b602002602001015161021760201b60201c565b50600101610084565b505f5b815181101561012a576101217fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217758383815181106100c3576100c36104e1565b506001016100e2565b5050600160045550889250506001600160a01b038216905061015f5760405163f44a4d1760e01b815260040160405180910390fd5b856001600160a01b0381166101875760405163f44a4d1760e01b815260040160405180910390fd5b6001600160a01b03881660808190526040805163416ecebf60e01b8152905163416ecebf916004808201926020929091908290030181865afa1580156101cf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101f391906104f5565b63ffffffff1660a0525050506001600160a01b0390931660c0525061055692505050565b5f7f74845de37cfabd357633214b47fa91ccd19b05b7c5a08ac22c187f811fb62bca8314801561026757505f838152602081815260408083206001600160a01b038616845290915290205460ff16155b156102b1576001805460159061028c90600160a81b90046001600160401b031661051f565b91906101000a8154816001600160401b0302191690836001600160401b031602179055505b6102bb83836102c4565b90505b92915050565b5f828152602081815260408083206001600160a01b038516845290915281205460ff16610364575f838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561031c3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016102be565b505f6102be565b80516001600160a01b0381168114610381575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126103a9575f5ffd5b81516001600160401b038111156103c2576103c2610386565b604051600582901b90603f8201601f191681016001600160401b03811182821017156103f0576103f0610386565b60405291825260208185018101929081018684111561040d575f5ffd5b6020860192505b83831015610433576104258361036b565b815260209283019201610414565b5095945050505050565b5f5f5f5f5f5f60c08789031215610452575f5ffd5b61045b8761036b565b95506104696020880161036b565b60408801519095506001600160401b03811115610484575f5ffd5b61049089828a0161039a565b94505061049f6060880161036b565b92506104ad6080880161036b565b60a08801519092506001600160401b038111156104c8575f5ffd5b6104d489828a0161039a565b9150509295509295509295565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215610505575f5ffd5b815163ffffffff81168114610518575f5ffd5b9392505050565b5f6001600160401b0382166002600160401b0319810161054d57634e487b7160e01b5f52601160045260245ffd5b60010192915050565b60805160a05160c051613c416106135f395f818161035e015281816108c001528181610b3201528181610c6c015261211c01525f81816107e501528181610b63015281816117a701528181611a2b0152611c5301525f81816104bb015281816113820152818161146c0152818161155401528181611636015281816116f1015281816117f1015281816118d201528181611d4201528181611e230152818161209d0152818161219c01528181612691015261274e0152613c415ff3fe608060405260043610610227575f3560e01c8063717e8a4211610129578063c358de0a116100a8578063cd88b9031161006d578063cd88b90314610745578063cfc3257014610764578063d2ae210414610777578063d547741f146107b5578063da2eb165146107d4575f5ffd5b8063c358de0a146106c4578063c416aa51146106e3578063c7b2370b14610707578063c8f8dcd114610726578063cb5026b914610692575f5ffd5b80638624ba07116100ee5780638624ba071461058b57806391d148541461059e5780639e944965146105e0578063a217fddf14610692578063c015bb7d146106a5575f5ffd5b8063717e8a42146104fc578063724e78da1461051b5780637401fccc1461053a578063741bef1a146105595780637cd4473414610578575f5ffd5b806327d12cd9116101b55780633d85ac331161017a5780633d85ac3314610461578063475b6d9e146104805780635c975abb146104935780636fad06f5146104aa578063709eb664146104dd575f5ffd5b806327d12cd9146103c45780632baf0be7146103f05780632de11376146104045780632f2ff15d1461042357806336568abe14610442575f5ffd5b80631095b6d7116101fb5780631095b6d7146102d357806316c38b3c146102f2578063248a9ca314610311578063252f5e3e1461034d57806326e67a3714610398575f5ffd5b8062bf2e801461022b57806301e336671461026457806301ffc9a7146102855780630894edf1146102b4575b5f5ffd5b348015610236575f5ffd5b5060015461024c90600160e81b900461ffff1681565b60405161ffff90911681526020015b60405180910390f35b34801561026f575f5ffd5b5061028361027e366004612a9e565b61081c565b005b348015610290575f5ffd5b506102a461029f366004612adc565b610844565b604051901515815260200161025b565b3480156102bf575f5ffd5b506102836102ce366004612b47565b61087a565b3480156102de575f5ffd5b506102836102ed366004612a9e565b610954565b3480156102fd575f5ffd5b5061028361030c366004612b9b565b610a72565b34801561031c575f5ffd5b5061033f61032b366004612bb6565b5f9081526020819052604090206001015490565b60405190815260200161025b565b348015610358575f5ffd5b506103807f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161025b565b3480156103a3575f5ffd5b506103b76103b2366004612be0565b610a96565b60405161025b9190612bf9565b3480156103cf575f5ffd5b506103e36103de366004612b47565b610b19565b60405161025b9190612c6e565b3480156103fb575f5ffd5b5061033f5f1981565b34801561040f575f5ffd5b506102a461041e366004612c81565b610d76565b34801561042e575f5ffd5b5061028361043d366004612c9c565b610e2a565b34801561044d575f5ffd5b5061028361045c366004612c9c565b610e4e565b34801561046c575f5ffd5b5061028361047b366004612cca565b610e67565b61028361048e366004612d79565b610ff1565b34801561049e575f5ffd5b5060015460ff166102a4565b3480156104b5575f5ffd5b506103807f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e8575f5ffd5b5061033f6104f7366004612dfa565b611032565b348015610507575f5ffd5b5061033f610516366004612dfa565b611135565b348015610526575f5ffd5b50610283610535366004612c81565b611264565b348015610545575f5ffd5b506103e3610554366004612b47565b611307565b348015610564575f5ffd5b50600254610380906001600160a01b031681565b610283610586366004612e76565b611617565b610283610599366004612f3f565b61177e565b3480156105a9575f5ffd5b506102a46105b8366004612c9c565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b3480156105eb575f5ffd5b5061064f6105fa366004612be0565b60056020525f9081526040902080546001909101546001600160401b038083169261ffff68010000000000000000820416926001600160801b03600160501b90920482169291811691600160801b9091041685565b604080516001600160401b03968716815261ffff90951660208601526001600160801b03938416908501529116606083015291909116608082015260a00161025b565b34801561069d575f5ffd5b5061033f5f81565b3480156106b0575f5ffd5b5061033f6106bf366004612fb0565b611992565b3480156106cf575f5ffd5b506102836106de366004613000565b611ad4565b3480156106ee575f5ffd5b506001546103809061010090046001600160a01b031681565b348015610712575f5ffd5b50610283610721366004612c81565b611b42565b348015610731575f5ffd5b5061033f610740366004612fb0565b611be4565b348015610750575f5ffd5b5061028361075f366004613019565b611cfa565b610283610772366004613098565b611d30565b348015610782575f5ffd5b5060015461079d90600160a81b90046001600160401b031681565b6040516001600160401b03909116815260200161025b565b3480156107c0575f5ffd5b506102836107cf366004612c9c565b611edd565b3480156107df575f5ffd5b506108077f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161025b565b5f516020613bec5f395f51905f5261083381611f01565b61083e848484611f0b565b50505050565b5f6001600160e01b03198216637965db0b60e01b148061087457506301ffc9a760e01b6001600160e01b03198316145b92915050565b610882611f2e565b5f61088e848484610b19565b905060018160038111156108a4576108a4612c3e565b0361092b57604051630894edf160e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630894edf1906108f9908790879087906004016130f1565b5f604051808303815f87803b158015610910575f5ffd5b505af1158015610922573d5f5f3e3d5ffd5b50505050610944565b604051633152adcf60e11b815260040160405180910390fd5b5061094f6001600455565b505050565b5f516020613bec5f395f51905f5261096b81611f01565b6001600160a01b0384165f9081527f9b50f4667d2d24216ccbf0dce3a90c0f620fa4d895e7b069d80ff6247fd25620602052604090205460ff166109c257604051635ee08b9760e01b815260040160405180910390fd5b604051637ecdf29160e11b81526001600160a01b0384811660048301526024820184905285169063fd9be522906044015f604051808303815f87803b158015610a09575f5ffd5b505af1158015610a1b573d5f5f3e3d5ffd5b5050604080516001600160a01b038089168252871660208201529081018590527f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb925060600190505b60405180910390a150505050565b5f610a7c81611f01565b8115610a8e57610a8a611f58565b5050565b610a8a611fac565b63ffffffff81165f90815260036020908152604091829020805483518184028101840190945280845260609392830182828015610b0d57602002820191905f5260205f20905f905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411610ade5790505b50505050509050919050565b60405163c40ff83560e01b81525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c40ff83590610b8b90879087907f000000000000000000000000000000000000000000000000000000000000000090600401613114565b5f6040518083038186803b158015610ba1575f5ffd5b505afa158015610bb3573d5f5f3e3d5ffd5b505050505f610bc28585611fe5565b90505f6040518060600160405280610bda8888611ff6565b63ffffffff168152602001610bef8888612018565b8152602001610bfe8888612030565b6001600160401b031690529050610c158183612052565b610c2457600392505050610d6f565b610c2f818386612114565b610c3e57600292505050610d6f565b80516040516343ea4fa960e01b81526001600160a01b03848116600483015263ffffffff90921660248201527f00000000000000000000000000000000000000000000000000000000000000009091169063e084d9529082906343ea4fa9906044015f60405180830381865afa158015610cba573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610ce19190810190613256565b8888604051610cf192919061332e565b6040519081900381206001600160e01b031960e085901b168252610d1a92918990600401613380565b602060405180830381865afa158015610d35573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d599190613408565b15610d6957600192505050610d6f565b5f925050505b9392505050565b6001600160a01b0381165f9081527f93c430521711328044ae92d0f1f1286cf040bc4a382f1642bd89984e86630553602052604081205460ff1615610dbc57505f919050565b600154600160a81b90046001600160401b03161580610e1157506001600160a01b0382165f9081527f4ac82e3087b7dedf7f532cbc6915c722df8c1e31f1388c318a617b52760eaf8b602052604090205460ff165b15610e1e57506001919050565b505f919050565b919050565b5f82815260208190526040902060010154610e4481611f01565b61083e838361221b565b60405163dec9f03160e01b815260040160405180910390fd5b5f516020613bec5f395f51905f52610e7e81611f01565b815f5b81811015610fbf575f858583818110610e9c57610e9c613423565b905060c00201803603810190610eb2919061344d565b6040805160a080820183526020808501516001600160401b03908116845260608087015161ffff9081168487019081526080808a01516001600160801b03908116898b01908152978b01518116948901948552898b01518616918901918252995163ffffffff165f90815260059096529790942095518654945195518916600160501b027fffffffffffff00000000000000000000000000000000ffffffffffffffffffff96909216680100000000000000000269ffffffffffffffffffff199095169084161793909317939093169190911783559051600192830180549451909216600160801b026001600160c01b031990941694169390931791909117909155919091019050610e81565b507fb99f6de5e22c60c178b03bfacf2daeb4b6089f5b37e0fe2c48a5d5141191fc538484604051610a649291906134d2565b5f516020613bec5f395f51905f5261100881611f01565b611010611f2e565b61101e8787878787876122bf565b506110296001600455565b50505050505050565b5f8461103d81610d76565b61105a57604051634ab5ebcd60e01b815260040160405180910390fd5b611062612423565b6040805160a0810182526002546001600160a01b03908116825263ffffffff8a1660208084018290528a831684860152606084018a905260015461ffff600160e81b82041660808601525f92835260059091529084902093516321a7700b60e11b815292936101009091049091169163434ee016916110ea918591908a908a9060040161359a565b602060405180830381865afa158015611105573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611129919061365c565b98975050505050505050565b5f7f724aface199fe5bed93ae8508474576a9adf3dc443b2c451842a2242919f19de61116081611f01565b8561116a81610d76565b61118757604051634ab5ebcd60e01b815260040160405180910390fd5b61118f612423565b6040805160a0810182526002546001600160a01b03908116825263ffffffff8b1660208084018290528b831684860152606084018b905260015461ffff600160e81b82041660808601525f9283526005909152908490209351632b377bb160e11b815292936101009091049091169163566ef76291611217918591908b908b9060040161359a565b6020604051808303815f875af1158015611233573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611257919061365c565b9998505050505050505050565b5f516020613bec5f395f51905f5261127b81611f01565b816001600160a01b0381166112a35760405163f44a4d1760e01b815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385169081179091556040519081527ff724a45d041687842411f2b977ef22ab8f43c8f1104f4592b42a00f9b34a643d906020015b60405180910390a1505050565b5f5f6113138585611fe5565b90505f604051806060016040528061132b8888611ff6565b63ffffffff1681526020016113408888612018565b815260200161134f8888612030565b6001600160401b0316905280516020820151604080840151905163c9fc7bcd60e01b81529394505f936001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169363c9fc7bcd936113e79389936004016001600160a01b0394909416845263ffffffff92909216602084015260408301526001600160401b0316606082015260800190565b602060405180830381865afa158015611402573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611426919061365c565b9050801580156114f15750815160208301516040516305b17bb760e41b81526001600160a01b03868116600483015263ffffffff909316602482015260448101919091527f000000000000000000000000000000000000000000000000000000000000000090911690635b17bb7090606401602060405180830381865afa1580156114b3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114d79190613673565b6001600160401b031682604001516001600160401b031611155b156115025760039350505050610d6f565b5f19811480159061151257508481145b80156115d957508151602083015160405163283750ff60e21b81526001600160a01b03868116600483015263ffffffff909316602482015260448101919091527f00000000000000000000000000000000000000000000000000000000000000009091169063a0dd43fc90606401602060405180830381865afa15801561159b573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115bf9190613673565b6001600160401b031682604001516001600160401b031611155b156115ea5760029350505050610d6f565b80158015906115fa57505f198114155b1561160b5760019350505050610d6f565b505f9695505050505050565b61161f611f2e565b6040516391d20fa160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391d20fa1908390349061167d908e908e908e908e908e908e908e908e9060040161368e565b5f604051808303818589803b158015611694575f5ffd5b5088f194505050505080156116a7575060015b611769573d8080156116d4576040519150601f19603f3d011682016040523d82523d5f602084013e6116d9565b606091505b506040516334bff35b60e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063697fe6b69061173a908d908d908d908d90899034908f908f908f908f908e9060040161371f565b5f604051808303815f87803b158015611751575f5ffd5b505af1158015611763573d5f5f3e3d5ffd5b50505050505b6117736001600455565b505050505050505050565b5f516020613bec5f395f51905f5261179581611f01565b61179d611f2e565b5f6117d8602084017f00000000000000000000000000000000000000000000000000000000000000006117d08287612c81565b8989896122bf565b90505f6117e582346137bc565b90506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016630c0c389e60e0860135836020880161182a818a612c81565b60808a013561183c60a08c018c6137cf565b61184960c08e018e6137cf565b6040518a63ffffffff1660e01b815260040161186b979695949392919061384e565b5f604051808303818589803b158015611882575f5ffd5b5088f19450505050508015611895575060015b61197f573d8080156118c2576040519150601f19603f3d011682016040523d82523d5f602084013e6118c7565b606091505b506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016636bf73fa3602087016119058189612c81565b608089013560e08a01358761191d60a08d018d6137cf565b61192a60c08f018f6137cf565b8b6040518b63ffffffff1660e01b81526004016119509a999897969594939291906138a4565b5f604051808303815f87803b158015611967575f5ffd5b505af1158015611979573d5f5f3e3d5ffd5b50505050505b505061198b6001600455565b5050505050565b5f7f724aface199fe5bed93ae8508474576a9adf3dc443b2c451842a2242919f19de6119bd81611f01565b846119c781610d76565b6119e457604051634ab5ebcd60e01b815260040160405180910390fd5b6119ec612423565b604080516060810182526002546001600160a01b03908116825288811660208084019190915260015461ffff600160e81b8204168486015263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000165f90815260059092529084902093516319400de160e21b8152929361010090910490911691636500378491611a89918591908b908b90600401613921565b6020604051808303815f875af1158015611aa5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ac9919061365c565b979650505050505050565b5f516020613bec5f395f51905f52611aeb81611f01565b6001805461ffff60e81b1916600160e81b61ffff8516908102919091179091556040519081527f7af0ac740036ffb1c97b03697859d729e80a44ae5030543d64971c313565ab4d9060200160405180910390a15050565b5f516020613bec5f395f51905f52611b5981611f01565b816001600160a01b038116611b815760405163f44a4d1760e01b815260040160405180910390fd5b6001805474ffffffffffffffffffffffffffffffffffffffff0019166101006001600160a01b038616908102919091179091556040519081527f1399be28223800f8669b3ba5f8721d9fc16fc4e8d0bbf98378791c8c5a3015e0906020016112fa565b5f83611bef81610d76565b611c0c57604051634ab5ebcd60e01b815260040160405180910390fd5b611c14612423565b604080516060810182526002546001600160a01b03908116825287811660208084019190915260015461ffff600160e81b8204168486015263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000165f90815260059092529084902093516319be3d4f60e11b815292936101009091049091169163337c7a9e91611cb1918591908a908a90600401613921565b602060405180830381865afa158015611ccc573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cf0919061365c565b9695505050505050565b5f516020613bec5f395f51905f52611d1181611f01565b63ffffffff84165f90815260036020526040902061198b9084846129d2565b611d38611f2e565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016630c0c389e60e08301353460208501611d7b8187612c81565b6080870135611d8d60a08901896137cf565b611d9a60c08b018b6137cf565b6040518a63ffffffff1660e01b8152600401611dbc979695949392919061384e565b5f604051808303818589803b158015611dd3575f5ffd5b5088f19450505050508015611de6575060015b611ed0573d808015611e13576040519150601f19603f3d011682016040523d82523d5f602084013e611e18565b606091505b506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016636bf73fa360208401611e568186612c81565b608086013560e087013534611e6e60a08a018a6137cf565b611e7b60c08c018c6137cf565b8b6040518b63ffffffff1660e01b8152600401611ea19a999897969594939291906138a4565b5f604051808303815f87803b158015611eb8575f5ffd5b505af1158015611eca573d5f5f3e3d5ffd5b50505050505b611eda6001600455565b50565b5f82815260208190526040902060010154611ef781611f01565b61083e8383612449565b611eda81336124ec565b6001600160a01b038316611f235761094f8282612543565b61094f8383836125ec565b600260045403611f5157604051633ee5aeb560e01b815260040160405180910390fd5b6002600455565b611f60612423565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a1565b611fb4612627565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33611f8f565b5f610d6f611ff3848461264a565b90565b5f612005600d600984866139c9565b61200e916139f0565b60e01c9392505050565b5f612027602d600d84866139c9565b610d6f91613a28565b5f61203f6009600184866139c9565b61204891613a45565b60c01c9392505050565b6040805163861e1ca560e01b8152835163ffffffff16600482015260208401516024820152908301516001600160401b031660448201526001600160a01b0382811660648301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063861e1ca590608401602060405180830381865afa925050508015612102575060408051601f3d908101601f191682019092526120ff91810190613408565b60015b61210d57505f610874565b9050610874565b5f61214184847f000000000000000000000000000000000000000000000000000000000000000085612659565b61214c57505f610d6f565b83516020850151604080870151905163c9fc7bcd60e01b81526001600160a01b03878116600483015263ffffffff909416602482015260448101929092526001600160401b0316606482015283917f0000000000000000000000000000000000000000000000000000000000000000169063c9fc7bcd90608401602060405180830381865afa1580156121e1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612205919061365c565b0361221157505f610d6f565b5060019392505050565b5f7f74845de37cfabd357633214b47fa91ccd19b05b7c5a08ac22c187f811fb62bca8314801561226b57505f838152602081815260408083206001600160a01b038616845290915290205460ff16155b156122b5576001805460159061229090600160a81b90046001600160401b0316613a7b565b91906101000a8154816001600160401b0302191690836001600160401b031602179055505b610d6f83836127da565b5f8281816001600160401b038111156122da576122da61313d565b604051908082528060200260200182016040528015612303578160200160208202803683370190505b5090505f5b828110156123d5575f87878381811061232357612323613423565b9050604002018036038101906123399190613aa5565b90505f815f01516001600160a01b0316826020015188906040515f60405180830381858888f193505050503d805f811461238e576040519150601f19603f3d011682016040523d82523d5f602084013e612393565b606091505b50509050808484815181106123aa576123aa613423565b9115156020928302919091018201528201516123c69087613afc565b95505050806001019050612308565b507f1f48172553121d8bf273ce457a5a3dd180d464e0add3e0143045b7fa039c346889898989898660405161240f96959493929190613b41565b60405180910390a150509695505050505050565b60015460ff16156124475760405163d93c066560e01b815260040160405180910390fd5b565b5f7f74845de37cfabd357633214b47fa91ccd19b05b7c5a08ac22c187f811fb62bca8314801561249857505f838152602081815260408083206001600160a01b038616845290915290205460ff165b156124e257600180546015906124bd90600160a81b90046001600160401b0316613bca565b91906101000a8154816001600160401b0302191690836001600160401b031602179055505b610d6f8383612881565b5f828152602081815260408083206001600160a01b038516845290915290205460ff16610a8a5760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044015b60405180910390fd5b6001600160a01b03821661256a576040516306b7a93160e41b815260040160405180910390fd5b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f81146125b3576040519150601f19603f3d011682016040523d82523d5f602084013e6125b8565b606091505b505090508061094f57604051631196f20d60e21b81526001600160a01b03841660048201526024810183905260440161253a565b6001600160a01b038216612613576040516306b7a93160e41b815260040160405180910390fd5b61094f6001600160a01b0384168383612902565b60015460ff1661244757604051638dfc202b60e01b815260040160405180910390fd5b5f6120276051603184866139c9565b8351604051639d7f977560e01b81526001600160a01b03858116600483015263ffffffff909216602482015283821660448201525f917f00000000000000000000000000000000000000000000000000000000000000001690639d7f977590606401602060405180830381865afa1580156126d6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126fa9190613408565b61270557505f6127d2565b6040805163c9a54a9960e01b8152865163ffffffff16600482015260208701516024820152908601516001600160401b031660448201526001600160a01b0385811660648301527f0000000000000000000000000000000000000000000000000000000000000000169063c9a54a9990608401602060405180830381865afa158015612793573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127b79190613408565b6127c257505f6127d2565b816127ce57505f6127d2565b5060015b949350505050565b5f828152602081815260408083206001600160a01b038516845290915281205460ff1661287a575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556128323390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610874565b505f610874565b5f828152602081815260408083206001600160a01b038516845290915281205460ff161561287a575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610874565b604080516001600160a01b03841660248201526044808201849052825180830390910181526064909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b178152825161094f93879390925f9283929183919082885af180612985576040513d5f823e3d81fd5b50505f513d9150811561299c5780600114156129a9565b6001600160a01b0384163b155b1561083e57604051635274afe760e01b81526001600160a01b038516600482015260240161253a565b828054828255905f5260205f2090601f01602090048101928215612a66579160200282015f5b83821115612a3857833560ff1683826101000a81548160ff021916908360ff16021790555092602001926001016020815f010492830192600103026129f8565b8015612a645782816101000a81549060ff02191690556001016020815f01049283019260010302612a38565b505b50612a72929150612a76565b5090565b5b80821115612a72575f8155600101612a77565b6001600160a01b0381168114611eda575f5ffd5b5f5f5f60608486031215612ab0575f5ffd5b8335612abb81612a8a565b92506020840135612acb81612a8a565b929592945050506040919091013590565b5f60208284031215612aec575f5ffd5b81356001600160e01b031981168114610d6f575f5ffd5b5f5f83601f840112612b13575f5ffd5b5081356001600160401b03811115612b29575f5ffd5b602083019150836020828501011115612b40575f5ffd5b9250929050565b5f5f5f60408486031215612b59575f5ffd5b83356001600160401b03811115612b6e575f5ffd5b612b7a86828701612b03565b909790965060209590950135949350505050565b8015158114611eda575f5ffd5b5f60208284031215612bab575f5ffd5b8135610d6f81612b8e565b5f60208284031215612bc6575f5ffd5b5035919050565b803563ffffffff81168114610e25575f5ffd5b5f60208284031215612bf0575f5ffd5b610d6f82612bcd565b602080825282518282018190525f918401906040840190835b81811015612c3357835160ff16835260209384019390920191600101612c12565b509095945050505050565b634e487b7160e01b5f52602160045260245ffd5b60048110611eda57634e487b7160e01b5f52602160045260245ffd5b60208101612c7b83612c52565b91905290565b5f60208284031215612c91575f5ffd5b8135610d6f81612a8a565b5f5f60408385031215612cad575f5ffd5b823591506020830135612cbf81612a8a565b809150509250929050565b5f5f60208385031215612cdb575f5ffd5b82356001600160401b03811115612cf0575f5ffd5b8301601f81018513612d00575f5ffd5b80356001600160401b03811115612d15575f5ffd5b85602060c083028401011115612d29575f5ffd5b6020919091019590945092505050565b5f5f83601f840112612d49575f5ffd5b5081356001600160401b03811115612d5f575f5ffd5b6020830191508360208260061b8501011115612b40575f5ffd5b5f5f5f5f5f5f86880360e0811215612d8f575f5ffd5b6060811215612d9c575f5ffd5b50869550612dac60608801612bcd565b94506080870135612dbc81612a8a565b935060a08701356001600160401b03811115612dd6575f5ffd5b612de289828a01612d39565b979a969950949794969560c090950135949350505050565b5f5f5f5f5f60808688031215612e0e575f5ffd5b612e1786612bcd565b94506020860135612e2781612a8a565b93506040860135925060608601356001600160401b03811115612e48575f5ffd5b612e5488828901612b03565b969995985093965092949392505050565b803561ffff81168114610e25575f5ffd5b5f5f5f5f5f5f5f5f5f60e08a8c031215612e8e575f5ffd5b8935612e9981612a8a565b985060208a0135612ea981612a8a565b975060408a01359650612ebe60608b01612e65565b955060808a01356001600160401b03811115612ed8575f5ffd5b612ee48c828d01612b03565b90965094505060a08a01356001600160401b03811115612f02575f5ffd5b612f0e8c828d01612b03565b9a9d999c50979a9699959894979660c00135949350505050565b5f6101008284031215612f39575f5ffd5b50919050565b5f5f5f5f60608587031215612f52575f5ffd5b84356001600160401b03811115612f67575f5ffd5b612f7387828801612d39565b9095509350506020850135915060408501356001600160401b03811115612f98575f5ffd5b612fa487828801612f28565b91505092959194509250565b5f5f5f60408486031215612fc2575f5ffd5b8335612fcd81612a8a565b925060208401356001600160401b03811115612fe7575f5ffd5b612ff386828701612b03565b9497909650939450505050565b5f60208284031215613010575f5ffd5b610d6f82612e65565b5f5f5f6040848603121561302b575f5ffd5b61303484612bcd565b925060208401356001600160401b0381111561304e575f5ffd5b8401601f8101861361305e575f5ffd5b80356001600160401b03811115613073575f5ffd5b8660208260051b8401011115613087575f5ffd5b939660209190910195509293505050565b5f602082840312156130a8575f5ffd5b81356001600160401b038111156130bd575f5ffd5b6127d284828501612f28565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f6131046040830185876130c9565b9050826020830152949350505050565b604081525f6131276040830185876130c9565b905063ffffffff83166020830152949350505050565b634e487b7160e01b5f52604160045260245ffd5b60405160c081016001600160401b03811182821017156131735761317361313d565b60405290565b604051601f8201601f191681016001600160401b03811182821017156131a1576131a161313d565b604052919050565b6001600160401b0381168114611eda575f5ffd5b8051610e25816131a9565b805160ff81168114610e25575f5ffd5b5f82601f8301126131e7575f5ffd5b81516001600160401b038111156132005761320061313d565b8060051b61321060208201613179565b9182526020818501810192908101908684111561322b575f5ffd5b6020860192505b83831015611cf057825161324581612a8a565b825260209283019290910190613232565b5f60208284031215613266575f5ffd5b81516001600160401b0381111561327b575f5ffd5b820160c0818503121561328c575f5ffd5b613294613151565b61329d826131bd565b81526132ab602083016131c8565b60208201526132bc604083016131c8565b60408201526132cd606083016131c8565b606082015260808201516001600160401b038111156132ea575f5ffd5b6132f6868285016131d8565b60808301525060a08201516001600160401b03811115613314575f5ffd5b613320868285016131d8565b60a083015250949350505050565b818382375f9101908152919050565b5f8151808452602084019350602083015f5b828110156133765781516001600160a01b031686526020958601959091019060010161334f565b5093949350505050565b606081526001600160401b03845116606082015260ff602085015116608082015260ff60408501511660a082015260ff60608501511660c08201525f608085015160c060e08401526133d661012084018261333d565b905060a0860151605f19848303016101008501526133f4828261333d565b602085019690965250505060400152919050565b5f60208284031215613418575f5ffd5b8151610d6f81612b8e565b634e487b7160e01b5f52603260045260245ffd5b80356001600160801b0381168114610e25575f5ffd5b5f60c082840312801561345e575f5ffd5b50613467613151565b61347083612bcd565b81526020830135613480816131a9565b60208201526040830135613493816131a9565b60408201526134a460608401612e65565b60608201526134b560808401613437565b60808201526134c660a08401613437565b60a08201529392505050565b602080825281018290525f8360408301825b858110156135905763ffffffff6134fa84612bcd565b168252602083013561350b816131a9565b6001600160401b031660208301526040830135613527816131a9565b6001600160401b0316604083015261ffff61354460608501612e65565b1660608301526001600160801b0361355e60808501613437565b16608083015261357060a08401613437565b6001600160801b031660a083015260c092830192909101906001016134e4565b5095945050505050565b6001600160a01b03855116815263ffffffff60208601511660208201526001600160a01b0360408601511660408201526060850151606082015261ffff608086015116608082015261364360a082018580546001600160401b038116835261ffff8160401c1660208401526001600160801b038160501c1660408401525060018101546001600160801b03811660608401526001600160401b038160801c166080840152505050565b6101606101408201525f611cf0610160830184866130c9565b5f6020828403121561366c575f5ffd5b5051919050565b5f60208284031215613683575f5ffd5b8151610d6f816131a9565b6001600160a01b03891681526001600160a01b038816602082015286604082015261ffff8616606082015260c060808201525f6136cf60c0830186886130c9565b82810360a08401526136e28185876130c9565b9b9a5050505050505050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b038c1681526001600160a01b038b16602082015289604082015261ffff891660608201528760808201528660a082015261012060c08201525f61376e610120830187896130c9565b82810360e08401526137818186886130c9565b905082810361010084015261379681856136f1565b9e9d5050505050505050505050505050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610874576108746137a8565b5f5f8335601e198436030181126137e4575f5ffd5b8301803591506001600160401b038211156137fd575f5ffd5b602001915036819003821315612b40575f5ffd5b63ffffffff61381f82612bcd565b16825260208181013590830152604081013561383a816131a9565b6001600160401b0381166040840152505050565b6138588189613811565b6001600160a01b038716606082015285608082015260e060a08201525f61388360e0830186886130c9565b82810360c08401526138968185876130c9565b9a9950505050505050505050565b6138ae818c613811565b6001600160a01b038a1660608201528860808201528760a08201528660c082015261014060e08201525f6138e7610140830187896130c9565b8281036101008401526138fb8186886130c9565b905082810361012084015261391081856136f1565b9d9c50505050505050505050505050565b6001600160a01b0385511681526001600160a01b03602086015116602082015261ffff60408601511660408201526139b0606082018580546001600160401b038116835261ffff8160401c1660208401526001600160801b038160501c1660408401525060018101546001600160801b03811660608401526001600160401b038160801c166080840152505050565b6101206101008201525f611cf0610120830184866130c9565b5f5f858511156139d7575f5ffd5b838611156139e3575f5ffd5b5050820193919092039150565b80356001600160e01b03198116906004841015613a21576001600160e01b0319600485900360031b81901b82161691505b5092915050565b80356020831015610874575f19602084900360031b1b1692915050565b80356001600160c01b03198116906008841015613a21576001600160c01b031960089490940360031b84901b1690921692915050565b5f6001600160401b0382166001600160401b038103613a9c57613a9c6137a8565b60010192915050565b5f6040828403128015613ab6575f5ffd5b50604080519081016001600160401b0381118282101715613ad957613ad961313d565b6040528235613ae781612a8a565b81526020928301359281019290925250919050565b80820180821115610874576108746137a8565b5f8151808452602084019350602083015f5b828110156133765781511515865260209586019590910190600101613b21565b5f60e08201613b50838a613811565b63ffffffff881660608401526001600160a01b038716608084015260e060a08401528490528461010083015f5b86811015613bb7578235613b9081612a8a565b6001600160a01b031682526020838101359083015260409283019290910190600101613b7d565b5083810360c08501526138968186613b0f565b5f6001600160401b03821680613be257613be26137a8565b5f19019291505056fea49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a2646970667358221220978432c8ea204632d1c1a08323f4a92762b72a1424e76fa94185a4ceda465cd464736f6c634300081e00330000000000000000000000001a44076050125825900e736c501f859c50fe728c000000000000000000000000c02ab410f0734efa3f14628780e6e695156024c200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000c03f31fd86a9077785b7bcf6598ce3598fa91113000000000000000000000000f6ea1b046522fe5a58124555b1acbc77fabdd7e500000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bb2ea70c9e858123480642cf96acbcce1372dce10000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f6ea1b046522fe5a58124555b1acbc77fabdd7e5
Deployed Bytecode
0x608060405260043610610227575f3560e01c8063717e8a4211610129578063c358de0a116100a8578063cd88b9031161006d578063cd88b90314610745578063cfc3257014610764578063d2ae210414610777578063d547741f146107b5578063da2eb165146107d4575f5ffd5b8063c358de0a146106c4578063c416aa51146106e3578063c7b2370b14610707578063c8f8dcd114610726578063cb5026b914610692575f5ffd5b80638624ba07116100ee5780638624ba071461058b57806391d148541461059e5780639e944965146105e0578063a217fddf14610692578063c015bb7d146106a5575f5ffd5b8063717e8a42146104fc578063724e78da1461051b5780637401fccc1461053a578063741bef1a146105595780637cd4473414610578575f5ffd5b806327d12cd9116101b55780633d85ac331161017a5780633d85ac3314610461578063475b6d9e146104805780635c975abb146104935780636fad06f5146104aa578063709eb664146104dd575f5ffd5b806327d12cd9146103c45780632baf0be7146103f05780632de11376146104045780632f2ff15d1461042357806336568abe14610442575f5ffd5b80631095b6d7116101fb5780631095b6d7146102d357806316c38b3c146102f2578063248a9ca314610311578063252f5e3e1461034d57806326e67a3714610398575f5ffd5b8062bf2e801461022b57806301e336671461026457806301ffc9a7146102855780630894edf1146102b4575b5f5ffd5b348015610236575f5ffd5b5060015461024c90600160e81b900461ffff1681565b60405161ffff90911681526020015b60405180910390f35b34801561026f575f5ffd5b5061028361027e366004612a9e565b61081c565b005b348015610290575f5ffd5b506102a461029f366004612adc565b610844565b604051901515815260200161025b565b3480156102bf575f5ffd5b506102836102ce366004612b47565b61087a565b3480156102de575f5ffd5b506102836102ed366004612a9e565b610954565b3480156102fd575f5ffd5b5061028361030c366004612b9b565b610a72565b34801561031c575f5ffd5b5061033f61032b366004612bb6565b5f9081526020819052604090206001015490565b60405190815260200161025b565b348015610358575f5ffd5b506103807f000000000000000000000000c02ab410f0734efa3f14628780e6e695156024c281565b6040516001600160a01b03909116815260200161025b565b3480156103a3575f5ffd5b506103b76103b2366004612be0565b610a96565b60405161025b9190612bf9565b3480156103cf575f5ffd5b506103e36103de366004612b47565b610b19565b60405161025b9190612c6e565b3480156103fb575f5ffd5b5061033f5f1981565b34801561040f575f5ffd5b506102a461041e366004612c81565b610d76565b34801561042e575f5ffd5b5061028361043d366004612c9c565b610e2a565b34801561044d575f5ffd5b5061028361045c366004612c9c565b610e4e565b34801561046c575f5ffd5b5061028361047b366004612cca565b610e67565b61028361048e366004612d79565b610ff1565b34801561049e575f5ffd5b5060015460ff166102a4565b3480156104b5575f5ffd5b506103807f0000000000000000000000001a44076050125825900e736c501f859c50fe728c81565b3480156104e8575f5ffd5b5061033f6104f7366004612dfa565b611032565b348015610507575f5ffd5b5061033f610516366004612dfa565b611135565b348015610526575f5ffd5b50610283610535366004612c81565b611264565b348015610545575f5ffd5b506103e3610554366004612b47565b611307565b348015610564575f5ffd5b50600254610380906001600160a01b031681565b610283610586366004612e76565b611617565b610283610599366004612f3f565b61177e565b3480156105a9575f5ffd5b506102a46105b8366004612c9c565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b3480156105eb575f5ffd5b5061064f6105fa366004612be0565b60056020525f9081526040902080546001909101546001600160401b038083169261ffff68010000000000000000820416926001600160801b03600160501b90920482169291811691600160801b9091041685565b604080516001600160401b03968716815261ffff90951660208601526001600160801b03938416908501529116606083015291909116608082015260a00161025b565b34801561069d575f5ffd5b5061033f5f81565b3480156106b0575f5ffd5b5061033f6106bf366004612fb0565b611992565b3480156106cf575f5ffd5b506102836106de366004613000565b611ad4565b3480156106ee575f5ffd5b506001546103809061010090046001600160a01b031681565b348015610712575f5ffd5b50610283610721366004612c81565b611b42565b348015610731575f5ffd5b5061033f610740366004612fb0565b611be4565b348015610750575f5ffd5b5061028361075f366004613019565b611cfa565b610283610772366004613098565b611d30565b348015610782575f5ffd5b5060015461079d90600160a81b90046001600160401b031681565b6040516001600160401b03909116815260200161025b565b3480156107c0575f5ffd5b506102836107cf366004612c9c565b611edd565b3480156107df575f5ffd5b506108077f000000000000000000000000000000000000000000000000000000000000759581565b60405163ffffffff909116815260200161025b565b5f516020613bec5f395f51905f5261083381611f01565b61083e848484611f0b565b50505050565b5f6001600160e01b03198216637965db0b60e01b148061087457506301ffc9a760e01b6001600160e01b03198316145b92915050565b610882611f2e565b5f61088e848484610b19565b905060018160038111156108a4576108a4612c3e565b0361092b57604051630894edf160e01b81526001600160a01b037f000000000000000000000000c02ab410f0734efa3f14628780e6e695156024c21690630894edf1906108f9908790879087906004016130f1565b5f604051808303815f87803b158015610910575f5ffd5b505af1158015610922573d5f5f3e3d5ffd5b50505050610944565b604051633152adcf60e11b815260040160405180910390fd5b5061094f6001600455565b505050565b5f516020613bec5f395f51905f5261096b81611f01565b6001600160a01b0384165f9081527f9b50f4667d2d24216ccbf0dce3a90c0f620fa4d895e7b069d80ff6247fd25620602052604090205460ff166109c257604051635ee08b9760e01b815260040160405180910390fd5b604051637ecdf29160e11b81526001600160a01b0384811660048301526024820184905285169063fd9be522906044015f604051808303815f87803b158015610a09575f5ffd5b505af1158015610a1b573d5f5f3e3d5ffd5b5050604080516001600160a01b038089168252871660208201529081018590527f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb925060600190505b60405180910390a150505050565b5f610a7c81611f01565b8115610a8e57610a8a611f58565b5050565b610a8a611fac565b63ffffffff81165f90815260036020908152604091829020805483518184028101840190945280845260609392830182828015610b0d57602002820191905f5260205f20905f905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411610ade5790505b50505050509050919050565b60405163c40ff83560e01b81525f906001600160a01b037f000000000000000000000000c02ab410f0734efa3f14628780e6e695156024c2169063c40ff83590610b8b90879087907f000000000000000000000000000000000000000000000000000000000000759590600401613114565b5f6040518083038186803b158015610ba1575f5ffd5b505afa158015610bb3573d5f5f3e3d5ffd5b505050505f610bc28585611fe5565b90505f6040518060600160405280610bda8888611ff6565b63ffffffff168152602001610bef8888612018565b8152602001610bfe8888612030565b6001600160401b031690529050610c158183612052565b610c2457600392505050610d6f565b610c2f818386612114565b610c3e57600292505050610d6f565b80516040516343ea4fa960e01b81526001600160a01b03848116600483015263ffffffff90921660248201527f000000000000000000000000c02ab410f0734efa3f14628780e6e695156024c29091169063e084d9529082906343ea4fa9906044015f60405180830381865afa158015610cba573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610ce19190810190613256565b8888604051610cf192919061332e565b6040519081900381206001600160e01b031960e085901b168252610d1a92918990600401613380565b602060405180830381865afa158015610d35573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d599190613408565b15610d6957600192505050610d6f565b5f925050505b9392505050565b6001600160a01b0381165f9081527f93c430521711328044ae92d0f1f1286cf040bc4a382f1642bd89984e86630553602052604081205460ff1615610dbc57505f919050565b600154600160a81b90046001600160401b03161580610e1157506001600160a01b0382165f9081527f4ac82e3087b7dedf7f532cbc6915c722df8c1e31f1388c318a617b52760eaf8b602052604090205460ff165b15610e1e57506001919050565b505f919050565b919050565b5f82815260208190526040902060010154610e4481611f01565b61083e838361221b565b60405163dec9f03160e01b815260040160405180910390fd5b5f516020613bec5f395f51905f52610e7e81611f01565b815f5b81811015610fbf575f858583818110610e9c57610e9c613423565b905060c00201803603810190610eb2919061344d565b6040805160a080820183526020808501516001600160401b03908116845260608087015161ffff9081168487019081526080808a01516001600160801b03908116898b01908152978b01518116948901948552898b01518616918901918252995163ffffffff165f90815260059096529790942095518654945195518916600160501b027fffffffffffff00000000000000000000000000000000ffffffffffffffffffff96909216680100000000000000000269ffffffffffffffffffff199095169084161793909317939093169190911783559051600192830180549451909216600160801b026001600160c01b031990941694169390931791909117909155919091019050610e81565b507fb99f6de5e22c60c178b03bfacf2daeb4b6089f5b37e0fe2c48a5d5141191fc538484604051610a649291906134d2565b5f516020613bec5f395f51905f5261100881611f01565b611010611f2e565b61101e8787878787876122bf565b506110296001600455565b50505050505050565b5f8461103d81610d76565b61105a57604051634ab5ebcd60e01b815260040160405180910390fd5b611062612423565b6040805160a0810182526002546001600160a01b03908116825263ffffffff8a1660208084018290528a831684860152606084018a905260015461ffff600160e81b82041660808601525f92835260059091529084902093516321a7700b60e11b815292936101009091049091169163434ee016916110ea918591908a908a9060040161359a565b602060405180830381865afa158015611105573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611129919061365c565b98975050505050505050565b5f7f724aface199fe5bed93ae8508474576a9adf3dc443b2c451842a2242919f19de61116081611f01565b8561116a81610d76565b61118757604051634ab5ebcd60e01b815260040160405180910390fd5b61118f612423565b6040805160a0810182526002546001600160a01b03908116825263ffffffff8b1660208084018290528b831684860152606084018b905260015461ffff600160e81b82041660808601525f9283526005909152908490209351632b377bb160e11b815292936101009091049091169163566ef76291611217918591908b908b9060040161359a565b6020604051808303815f875af1158015611233573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611257919061365c565b9998505050505050505050565b5f516020613bec5f395f51905f5261127b81611f01565b816001600160a01b0381166112a35760405163f44a4d1760e01b815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385169081179091556040519081527ff724a45d041687842411f2b977ef22ab8f43c8f1104f4592b42a00f9b34a643d906020015b60405180910390a1505050565b5f5f6113138585611fe5565b90505f604051806060016040528061132b8888611ff6565b63ffffffff1681526020016113408888612018565b815260200161134f8888612030565b6001600160401b0316905280516020820151604080840151905163c9fc7bcd60e01b81529394505f936001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c169363c9fc7bcd936113e79389936004016001600160a01b0394909416845263ffffffff92909216602084015260408301526001600160401b0316606082015260800190565b602060405180830381865afa158015611402573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611426919061365c565b9050801580156114f15750815160208301516040516305b17bb760e41b81526001600160a01b03868116600483015263ffffffff909316602482015260448101919091527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c90911690635b17bb7090606401602060405180830381865afa1580156114b3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114d79190613673565b6001600160401b031682604001516001600160401b031611155b156115025760039350505050610d6f565b5f19811480159061151257508481145b80156115d957508151602083015160405163283750ff60e21b81526001600160a01b03868116600483015263ffffffff909316602482015260448101919091527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c9091169063a0dd43fc90606401602060405180830381865afa15801561159b573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115bf9190613673565b6001600160401b031682604001516001600160401b031611155b156115ea5760029350505050610d6f565b80158015906115fa57505f198114155b1561160b5760019350505050610d6f565b505f9695505050505050565b61161f611f2e565b6040516391d20fa160e01b81526001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c16906391d20fa1908390349061167d908e908e908e908e908e908e908e908e9060040161368e565b5f604051808303818589803b158015611694575f5ffd5b5088f194505050505080156116a7575060015b611769573d8080156116d4576040519150601f19603f3d011682016040523d82523d5f602084013e6116d9565b606091505b506040516334bff35b60e11b81526001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c169063697fe6b69061173a908d908d908d908d90899034908f908f908f908f908e9060040161371f565b5f604051808303815f87803b158015611751575f5ffd5b505af1158015611763573d5f5f3e3d5ffd5b50505050505b6117736001600455565b505050505050505050565b5f516020613bec5f395f51905f5261179581611f01565b61179d611f2e565b5f6117d8602084017f00000000000000000000000000000000000000000000000000000000000075956117d08287612c81565b8989896122bf565b90505f6117e582346137bc565b90506001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c16630c0c389e60e0860135836020880161182a818a612c81565b60808a013561183c60a08c018c6137cf565b61184960c08e018e6137cf565b6040518a63ffffffff1660e01b815260040161186b979695949392919061384e565b5f604051808303818589803b158015611882575f5ffd5b5088f19450505050508015611895575060015b61197f573d8080156118c2576040519150601f19603f3d011682016040523d82523d5f602084013e6118c7565b606091505b506001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c16636bf73fa3602087016119058189612c81565b608089013560e08a01358761191d60a08d018d6137cf565b61192a60c08f018f6137cf565b8b6040518b63ffffffff1660e01b81526004016119509a999897969594939291906138a4565b5f604051808303815f87803b158015611967575f5ffd5b505af1158015611979573d5f5f3e3d5ffd5b50505050505b505061198b6001600455565b5050505050565b5f7f724aface199fe5bed93ae8508474576a9adf3dc443b2c451842a2242919f19de6119bd81611f01565b846119c781610d76565b6119e457604051634ab5ebcd60e01b815260040160405180910390fd5b6119ec612423565b604080516060810182526002546001600160a01b03908116825288811660208084019190915260015461ffff600160e81b8204168486015263ffffffff7f0000000000000000000000000000000000000000000000000000000000007595165f90815260059092529084902093516319400de160e21b8152929361010090910490911691636500378491611a89918591908b908b90600401613921565b6020604051808303815f875af1158015611aa5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ac9919061365c565b979650505050505050565b5f516020613bec5f395f51905f52611aeb81611f01565b6001805461ffff60e81b1916600160e81b61ffff8516908102919091179091556040519081527f7af0ac740036ffb1c97b03697859d729e80a44ae5030543d64971c313565ab4d9060200160405180910390a15050565b5f516020613bec5f395f51905f52611b5981611f01565b816001600160a01b038116611b815760405163f44a4d1760e01b815260040160405180910390fd5b6001805474ffffffffffffffffffffffffffffffffffffffff0019166101006001600160a01b038616908102919091179091556040519081527f1399be28223800f8669b3ba5f8721d9fc16fc4e8d0bbf98378791c8c5a3015e0906020016112fa565b5f83611bef81610d76565b611c0c57604051634ab5ebcd60e01b815260040160405180910390fd5b611c14612423565b604080516060810182526002546001600160a01b03908116825287811660208084019190915260015461ffff600160e81b8204168486015263ffffffff7f0000000000000000000000000000000000000000000000000000000000007595165f90815260059092529084902093516319be3d4f60e11b815292936101009091049091169163337c7a9e91611cb1918591908a908a90600401613921565b602060405180830381865afa158015611ccc573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cf0919061365c565b9695505050505050565b5f516020613bec5f395f51905f52611d1181611f01565b63ffffffff84165f90815260036020526040902061198b9084846129d2565b611d38611f2e565b6001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c16630c0c389e60e08301353460208501611d7b8187612c81565b6080870135611d8d60a08901896137cf565b611d9a60c08b018b6137cf565b6040518a63ffffffff1660e01b8152600401611dbc979695949392919061384e565b5f604051808303818589803b158015611dd3575f5ffd5b5088f19450505050508015611de6575060015b611ed0573d808015611e13576040519150601f19603f3d011682016040523d82523d5f602084013e611e18565b606091505b506001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c16636bf73fa360208401611e568186612c81565b608086013560e087013534611e6e60a08a018a6137cf565b611e7b60c08c018c6137cf565b8b6040518b63ffffffff1660e01b8152600401611ea19a999897969594939291906138a4565b5f604051808303815f87803b158015611eb8575f5ffd5b505af1158015611eca573d5f5f3e3d5ffd5b50505050505b611eda6001600455565b50565b5f82815260208190526040902060010154611ef781611f01565b61083e8383612449565b611eda81336124ec565b6001600160a01b038316611f235761094f8282612543565b61094f8383836125ec565b600260045403611f5157604051633ee5aeb560e01b815260040160405180910390fd5b6002600455565b611f60612423565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a1565b611fb4612627565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33611f8f565b5f610d6f611ff3848461264a565b90565b5f612005600d600984866139c9565b61200e916139f0565b60e01c9392505050565b5f612027602d600d84866139c9565b610d6f91613a28565b5f61203f6009600184866139c9565b61204891613a45565b60c01c9392505050565b6040805163861e1ca560e01b8152835163ffffffff16600482015260208401516024820152908301516001600160401b031660448201526001600160a01b0382811660648301525f917f0000000000000000000000001a44076050125825900e736c501f859c50fe728c9091169063861e1ca590608401602060405180830381865afa925050508015612102575060408051601f3d908101601f191682019092526120ff91810190613408565b60015b61210d57505f610874565b9050610874565b5f61214184847f000000000000000000000000c02ab410f0734efa3f14628780e6e695156024c285612659565b61214c57505f610d6f565b83516020850151604080870151905163c9fc7bcd60e01b81526001600160a01b03878116600483015263ffffffff909416602482015260448101929092526001600160401b0316606482015283917f0000000000000000000000001a44076050125825900e736c501f859c50fe728c169063c9fc7bcd90608401602060405180830381865afa1580156121e1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612205919061365c565b0361221157505f610d6f565b5060019392505050565b5f7f74845de37cfabd357633214b47fa91ccd19b05b7c5a08ac22c187f811fb62bca8314801561226b57505f838152602081815260408083206001600160a01b038616845290915290205460ff16155b156122b5576001805460159061229090600160a81b90046001600160401b0316613a7b565b91906101000a8154816001600160401b0302191690836001600160401b031602179055505b610d6f83836127da565b5f8281816001600160401b038111156122da576122da61313d565b604051908082528060200260200182016040528015612303578160200160208202803683370190505b5090505f5b828110156123d5575f87878381811061232357612323613423565b9050604002018036038101906123399190613aa5565b90505f815f01516001600160a01b0316826020015188906040515f60405180830381858888f193505050503d805f811461238e576040519150601f19603f3d011682016040523d82523d5f602084013e612393565b606091505b50509050808484815181106123aa576123aa613423565b9115156020928302919091018201528201516123c69087613afc565b95505050806001019050612308565b507f1f48172553121d8bf273ce457a5a3dd180d464e0add3e0143045b7fa039c346889898989898660405161240f96959493929190613b41565b60405180910390a150509695505050505050565b60015460ff16156124475760405163d93c066560e01b815260040160405180910390fd5b565b5f7f74845de37cfabd357633214b47fa91ccd19b05b7c5a08ac22c187f811fb62bca8314801561249857505f838152602081815260408083206001600160a01b038616845290915290205460ff165b156124e257600180546015906124bd90600160a81b90046001600160401b0316613bca565b91906101000a8154816001600160401b0302191690836001600160401b031602179055505b610d6f8383612881565b5f828152602081815260408083206001600160a01b038516845290915290205460ff16610a8a5760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044015b60405180910390fd5b6001600160a01b03821661256a576040516306b7a93160e41b815260040160405180910390fd5b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f81146125b3576040519150601f19603f3d011682016040523d82523d5f602084013e6125b8565b606091505b505090508061094f57604051631196f20d60e21b81526001600160a01b03841660048201526024810183905260440161253a565b6001600160a01b038216612613576040516306b7a93160e41b815260040160405180910390fd5b61094f6001600160a01b0384168383612902565b60015460ff1661244757604051638dfc202b60e01b815260040160405180910390fd5b5f6120276051603184866139c9565b8351604051639d7f977560e01b81526001600160a01b03858116600483015263ffffffff909216602482015283821660448201525f917f0000000000000000000000001a44076050125825900e736c501f859c50fe728c1690639d7f977590606401602060405180830381865afa1580156126d6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126fa9190613408565b61270557505f6127d2565b6040805163c9a54a9960e01b8152865163ffffffff16600482015260208701516024820152908601516001600160401b031660448201526001600160a01b0385811660648301527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c169063c9a54a9990608401602060405180830381865afa158015612793573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127b79190613408565b6127c257505f6127d2565b816127ce57505f6127d2565b5060015b949350505050565b5f828152602081815260408083206001600160a01b038516845290915281205460ff1661287a575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556128323390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610874565b505f610874565b5f828152602081815260408083206001600160a01b038516845290915281205460ff161561287a575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610874565b604080516001600160a01b03841660248201526044808201849052825180830390910181526064909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b178152825161094f93879390925f9283929183919082885af180612985576040513d5f823e3d81fd5b50505f513d9150811561299c5780600114156129a9565b6001600160a01b0384163b155b1561083e57604051635274afe760e01b81526001600160a01b038516600482015260240161253a565b828054828255905f5260205f2090601f01602090048101928215612a66579160200282015f5b83821115612a3857833560ff1683826101000a81548160ff021916908360ff16021790555092602001926001016020815f010492830192600103026129f8565b8015612a645782816101000a81549060ff02191690556001016020815f01049283019260010302612a38565b505b50612a72929150612a76565b5090565b5b80821115612a72575f8155600101612a77565b6001600160a01b0381168114611eda575f5ffd5b5f5f5f60608486031215612ab0575f5ffd5b8335612abb81612a8a565b92506020840135612acb81612a8a565b929592945050506040919091013590565b5f60208284031215612aec575f5ffd5b81356001600160e01b031981168114610d6f575f5ffd5b5f5f83601f840112612b13575f5ffd5b5081356001600160401b03811115612b29575f5ffd5b602083019150836020828501011115612b40575f5ffd5b9250929050565b5f5f5f60408486031215612b59575f5ffd5b83356001600160401b03811115612b6e575f5ffd5b612b7a86828701612b03565b909790965060209590950135949350505050565b8015158114611eda575f5ffd5b5f60208284031215612bab575f5ffd5b8135610d6f81612b8e565b5f60208284031215612bc6575f5ffd5b5035919050565b803563ffffffff81168114610e25575f5ffd5b5f60208284031215612bf0575f5ffd5b610d6f82612bcd565b602080825282518282018190525f918401906040840190835b81811015612c3357835160ff16835260209384019390920191600101612c12565b509095945050505050565b634e487b7160e01b5f52602160045260245ffd5b60048110611eda57634e487b7160e01b5f52602160045260245ffd5b60208101612c7b83612c52565b91905290565b5f60208284031215612c91575f5ffd5b8135610d6f81612a8a565b5f5f60408385031215612cad575f5ffd5b823591506020830135612cbf81612a8a565b809150509250929050565b5f5f60208385031215612cdb575f5ffd5b82356001600160401b03811115612cf0575f5ffd5b8301601f81018513612d00575f5ffd5b80356001600160401b03811115612d15575f5ffd5b85602060c083028401011115612d29575f5ffd5b6020919091019590945092505050565b5f5f83601f840112612d49575f5ffd5b5081356001600160401b03811115612d5f575f5ffd5b6020830191508360208260061b8501011115612b40575f5ffd5b5f5f5f5f5f5f86880360e0811215612d8f575f5ffd5b6060811215612d9c575f5ffd5b50869550612dac60608801612bcd565b94506080870135612dbc81612a8a565b935060a08701356001600160401b03811115612dd6575f5ffd5b612de289828a01612d39565b979a969950949794969560c090950135949350505050565b5f5f5f5f5f60808688031215612e0e575f5ffd5b612e1786612bcd565b94506020860135612e2781612a8a565b93506040860135925060608601356001600160401b03811115612e48575f5ffd5b612e5488828901612b03565b969995985093965092949392505050565b803561ffff81168114610e25575f5ffd5b5f5f5f5f5f5f5f5f5f60e08a8c031215612e8e575f5ffd5b8935612e9981612a8a565b985060208a0135612ea981612a8a565b975060408a01359650612ebe60608b01612e65565b955060808a01356001600160401b03811115612ed8575f5ffd5b612ee48c828d01612b03565b90965094505060a08a01356001600160401b03811115612f02575f5ffd5b612f0e8c828d01612b03565b9a9d999c50979a9699959894979660c00135949350505050565b5f6101008284031215612f39575f5ffd5b50919050565b5f5f5f5f60608587031215612f52575f5ffd5b84356001600160401b03811115612f67575f5ffd5b612f7387828801612d39565b9095509350506020850135915060408501356001600160401b03811115612f98575f5ffd5b612fa487828801612f28565b91505092959194509250565b5f5f5f60408486031215612fc2575f5ffd5b8335612fcd81612a8a565b925060208401356001600160401b03811115612fe7575f5ffd5b612ff386828701612b03565b9497909650939450505050565b5f60208284031215613010575f5ffd5b610d6f82612e65565b5f5f5f6040848603121561302b575f5ffd5b61303484612bcd565b925060208401356001600160401b0381111561304e575f5ffd5b8401601f8101861361305e575f5ffd5b80356001600160401b03811115613073575f5ffd5b8660208260051b8401011115613087575f5ffd5b939660209190910195509293505050565b5f602082840312156130a8575f5ffd5b81356001600160401b038111156130bd575f5ffd5b6127d284828501612f28565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f6131046040830185876130c9565b9050826020830152949350505050565b604081525f6131276040830185876130c9565b905063ffffffff83166020830152949350505050565b634e487b7160e01b5f52604160045260245ffd5b60405160c081016001600160401b03811182821017156131735761317361313d565b60405290565b604051601f8201601f191681016001600160401b03811182821017156131a1576131a161313d565b604052919050565b6001600160401b0381168114611eda575f5ffd5b8051610e25816131a9565b805160ff81168114610e25575f5ffd5b5f82601f8301126131e7575f5ffd5b81516001600160401b038111156132005761320061313d565b8060051b61321060208201613179565b9182526020818501810192908101908684111561322b575f5ffd5b6020860192505b83831015611cf057825161324581612a8a565b825260209283019290910190613232565b5f60208284031215613266575f5ffd5b81516001600160401b0381111561327b575f5ffd5b820160c0818503121561328c575f5ffd5b613294613151565b61329d826131bd565b81526132ab602083016131c8565b60208201526132bc604083016131c8565b60408201526132cd606083016131c8565b606082015260808201516001600160401b038111156132ea575f5ffd5b6132f6868285016131d8565b60808301525060a08201516001600160401b03811115613314575f5ffd5b613320868285016131d8565b60a083015250949350505050565b818382375f9101908152919050565b5f8151808452602084019350602083015f5b828110156133765781516001600160a01b031686526020958601959091019060010161334f565b5093949350505050565b606081526001600160401b03845116606082015260ff602085015116608082015260ff60408501511660a082015260ff60608501511660c08201525f608085015160c060e08401526133d661012084018261333d565b905060a0860151605f19848303016101008501526133f4828261333d565b602085019690965250505060400152919050565b5f60208284031215613418575f5ffd5b8151610d6f81612b8e565b634e487b7160e01b5f52603260045260245ffd5b80356001600160801b0381168114610e25575f5ffd5b5f60c082840312801561345e575f5ffd5b50613467613151565b61347083612bcd565b81526020830135613480816131a9565b60208201526040830135613493816131a9565b60408201526134a460608401612e65565b60608201526134b560808401613437565b60808201526134c660a08401613437565b60a08201529392505050565b602080825281018290525f8360408301825b858110156135905763ffffffff6134fa84612bcd565b168252602083013561350b816131a9565b6001600160401b031660208301526040830135613527816131a9565b6001600160401b0316604083015261ffff61354460608501612e65565b1660608301526001600160801b0361355e60808501613437565b16608083015261357060a08401613437565b6001600160801b031660a083015260c092830192909101906001016134e4565b5095945050505050565b6001600160a01b03855116815263ffffffff60208601511660208201526001600160a01b0360408601511660408201526060850151606082015261ffff608086015116608082015261364360a082018580546001600160401b038116835261ffff8160401c1660208401526001600160801b038160501c1660408401525060018101546001600160801b03811660608401526001600160401b038160801c166080840152505050565b6101606101408201525f611cf0610160830184866130c9565b5f6020828403121561366c575f5ffd5b5051919050565b5f60208284031215613683575f5ffd5b8151610d6f816131a9565b6001600160a01b03891681526001600160a01b038816602082015286604082015261ffff8616606082015260c060808201525f6136cf60c0830186886130c9565b82810360a08401526136e28185876130c9565b9b9a5050505050505050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b038c1681526001600160a01b038b16602082015289604082015261ffff891660608201528760808201528660a082015261012060c08201525f61376e610120830187896130c9565b82810360e08401526137818186886130c9565b905082810361010084015261379681856136f1565b9e9d5050505050505050505050505050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610874576108746137a8565b5f5f8335601e198436030181126137e4575f5ffd5b8301803591506001600160401b038211156137fd575f5ffd5b602001915036819003821315612b40575f5ffd5b63ffffffff61381f82612bcd565b16825260208181013590830152604081013561383a816131a9565b6001600160401b0381166040840152505050565b6138588189613811565b6001600160a01b038716606082015285608082015260e060a08201525f61388360e0830186886130c9565b82810360c08401526138968185876130c9565b9a9950505050505050505050565b6138ae818c613811565b6001600160a01b038a1660608201528860808201528760a08201528660c082015261014060e08201525f6138e7610140830187896130c9565b8281036101008401526138fb8186886130c9565b905082810361012084015261391081856136f1565b9d9c50505050505050505050505050565b6001600160a01b0385511681526001600160a01b03602086015116602082015261ffff60408601511660408201526139b0606082018580546001600160401b038116835261ffff8160401c1660208401526001600160801b038160501c1660408401525060018101546001600160801b03811660608401526001600160401b038160801c166080840152505050565b6101206101008201525f611cf0610120830184866130c9565b5f5f858511156139d7575f5ffd5b838611156139e3575f5ffd5b5050820193919092039150565b80356001600160e01b03198116906004841015613a21576001600160e01b0319600485900360031b81901b82161691505b5092915050565b80356020831015610874575f19602084900360031b1b1692915050565b80356001600160c01b03198116906008841015613a21576001600160c01b031960089490940360031b84901b1690921692915050565b5f6001600160401b0382166001600160401b038103613a9c57613a9c6137a8565b60010192915050565b5f6040828403128015613ab6575f5ffd5b50604080519081016001600160401b0381118282101715613ad957613ad961313d565b6040528235613ae781612a8a565b81526020928301359281019290925250919050565b80820180821115610874576108746137a8565b5f8151808452602084019350602083015f5b828110156133765781511515865260209586019590910190600101613b21565b5f60e08201613b50838a613811565b63ffffffff881660608401526001600160a01b038716608084015260e060a08401528490528461010083015f5b86811015613bb7578235613b9081612a8a565b6001600160a01b031682526020838101359083015260409283019290910190600101613b7d565b5083810360c08501526138968186613b0f565b5f6001600160401b03821680613be257613be26137a8565b5f19019291505056fea49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a2646970667358221220978432c8ea204632d1c1a08323f4a92762b72a1424e76fa94185a4ceda465cd464736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001a44076050125825900e736c501f859c50fe728c000000000000000000000000c02ab410f0734efa3f14628780e6e695156024c200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000c03f31fd86a9077785b7bcf6598ce3598fa91113000000000000000000000000f6ea1b046522fe5a58124555b1acbc77fabdd7e500000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bb2ea70c9e858123480642cf96acbcce1372dce10000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f6ea1b046522fe5a58124555b1acbc77fabdd7e5
-----Decoded View---------------
Arg [0] : _endpoint (address): 0x1a44076050125825900e736c501f859c50fE728c
Arg [1] : _receiveUln302 (address): 0xc02Ab410f0734EFa3F14628780e6e695156024C2
Arg [2] : _messageLibs (address[]): 0xbB2Ea70C9E858123480642Cf96acbcCE1372dCe1
Arg [3] : _priceFeed (address): 0xC03f31fD86a9077785b7bCf6598Ce3598Fa91113
Arg [4] : _roleAdmin (address): 0xf6Ea1B046522fe5a58124555b1Acbc77FabdD7E5
Arg [5] : _admins (address[]): 0xf6Ea1B046522fe5a58124555b1Acbc77FabdD7E5
-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 0000000000000000000000001a44076050125825900e736c501f859c50fe728c
Arg [1] : 000000000000000000000000c02ab410f0734efa3f14628780e6e695156024c2
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [3] : 000000000000000000000000c03f31fd86a9077785b7bcf6598ce3598fa91113
Arg [4] : 000000000000000000000000f6ea1b046522fe5a58124555b1acbc77fabdd7e5
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [7] : 000000000000000000000000bb2ea70c9e858123480642cf96acbcce1372dce1
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [9] : 000000000000000000000000f6ea1b046522fe5a58124555b1acbc77fabdd7e5
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.