More Info
Private Name Tags
ContractCreator
Latest 7 from a total of 7 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Register Collect... | 9059975 | 37 days ago | IN | 0 APE | 0.00186041 | ||||
Register Collect... | 9059878 | 37 days ago | IN | 0 APE | 0.00186043 | ||||
Set Required Con... | 9052052 | 37 days ago | IN | 0 APE | 0.00122347 | ||||
Set Peer | 9052051 | 37 days ago | IN | 0 APE | 0.0012106 | ||||
Set Required Con... | 9051960 | 37 days ago | IN | 0 APE | 0.00122347 | ||||
Set Peer | 9051956 | 37 days ago | IN | 0 APE | 0.0012106 | ||||
Grant Role | 9049950 | 37 days ago | IN | 0 APE | 0.0013038 |
Latest 17 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
10044631 | 22 days ago | 5 APE | ||||
10044631 | 22 days ago | 5 APE | ||||
10043652 | 22 days ago | 20 APE | ||||
10043652 | 22 days ago | 20 APE | ||||
9526670 | 29 days ago | 2.9 APE | ||||
9526670 | 29 days ago | 2.9 APE | ||||
9526584 | 29 days ago | 3.5 APE | ||||
9526584 | 29 days ago | 3.5 APE | ||||
9470262 | 30 days ago | 3.57345607 APE | ||||
9470262 | 30 days ago | 3.57345607 APE | ||||
9369925 | 32 days ago | 44 APE | ||||
9369925 | 32 days ago | 44 APE | ||||
9369709 | 32 days ago | 18 APE | ||||
9369709 | 32 days ago | 18 APE | ||||
9351488 | 32 days ago | 3.43467187 APE | ||||
9351488 | 32 days ago | 3.43467187 APE | ||||
9049943 | 37 days ago | Contract Creation | 0 APE |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Beacon
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import { ILayerZeroEndpointV2, MessagingFee, MessagingReceipt, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; import { ReadCodecV1, EVMCallComputeV1, EVMCallRequestV1 } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/ReadCodecV1.sol"; import {OAppRead} from "@layerzerolabs/oapp-evm/contracts/oapp/OAppRead.sol"; import {OAppOptionsType3} from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol"; import {OptionsBuilder} from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol"; import {AddressCast} from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {LibMap} from "solady/utils/LibMap.sol"; import {IExclusiveDelegateResolver} from "./interfaces/IExclusiveDelegateResolver.sol"; import {IDelegateRegistry} from "./interfaces/IDelegateRegistry.sol"; import {INFTShadow} from "./interfaces/INFTShadow.sol"; import {IOAppMapper} from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMapper.sol"; import {IOAppReducer} from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppReducer.sol"; import {SafeCall} from "./utils/SafeCall.sol"; import {CollectionConfig} from "./structs/CollectionConfig.sol"; import {ILayerZeroEndpointLocator} from "./interfaces/ILayerZeroEndpointLocator.sol"; /** * @notice The Beacon contract is responsible for managing the ownership of NFTs across multiple chains. * It uses LayerZero's OApp protocol to send messages between chains and maintain ownership records. */ contract Beacon is OAppRead, OAppOptionsType3, IOAppMapper, IOAppReducer, AccessControl { using OptionsBuilder for bytes; using AddressCast for bytes32; using AddressCast for address; using SafeCall for address; using LibMap for LibMap.Uint32Map; // The provided contract address is not configured error ContractNotConfigured(); // The shadow contract has already been deployed error CollectionAlreadyRegistered(); // The provided endpoint ID matches this contract's eid error InvalidEid(); // The caller is not the shadow contract error InvalidCaller(); // The caller is not the contract itself error OnlyInternalCalls(); // The payload hash does not match the expected hash error InvalidPayloadHash(); // The beneficiary is the zero address error BeneficiaryZeroAddress(); // The read channel is under the threshold error InvalidReadChannel(); // Punk adapter is already set error PunkAdapterAlreadySet(); // Punk adapter can only be set on mainnet error InvalidChain(); // The collection address is zero error ZeroAddress(); // The array is empty error ZeroLengthArray(); // The collection address and base collection address do not match error MismatchedCollectionAddress(); // The maximum gas allocation for lzReceive has been exceeded error MaxLzReceiveGasAllocationExceeded(); // lzRead returned an invalid state error InvalidOwner(); // The executor is not allowed error UnauthorizedExecutor(); // The read request has timed out error StaleReadRequest(); // The transfer failed error TransferFailed(); // The burn failed error BurnFailed(); // The mint failed error MintFailed(); // The unlock failed error UnlockFailed(); // The collection is not in shadow mode error CollectionNotInShadowMode(); // Emitted once the punk adapter is set event PunkAdapterSet(address indexed punkAdapter); // Emitted each time a collection is registered on this Beacon event Sent( uint32 indexed eid, address indexed baseCollectionAddress, address indexed collection, uint256[] tokenIds, address beneficiary ); // Emitted each time an ownership update is triggered event ReadTriggered( address indexed baseCollectionAddress, address indexed shadowCollectionAddress, uint32[] eids, uint256[] tokenIds ); // Emitted once for each collection registered on this Beacon event CollectionRegistered( address indexed collectionAddress, address indexed baseCollectionAddress, uint32 indexed baseCollectionEid ); // Emitted when a message fails and ends up in the cache event MessageCached(uint32 indexed srcEid, bytes32 indexed sender, uint64 nonce, bytes reason); // Emitted when a cached message is executed event CachedMessageExecuted(uint32 indexed srcEid, bytes32 indexed sender, uint64 nonce); // Emitted when the execution enforcement is set event EnforceExecutionSet(bool enforceExecutors); // Emitted when an executor is allowed or disallowed event AllowedExecutorSet(address executor, bool allowed); // Emitted when the required confirmations for an EID are set event RequiredConfirmationsSet(uint32 eid, uint16 confirmations); // Emitted when the read channel is set event ReadChannelSet(uint32 readChannel); // Constants for SafeCall uint256 private constant _SAFE_CALL_BUFFER = 50_000; // costs used for generating LZRead options uint128 private constant _DELEGATION_UPDATE_COST = 203_911; // worst case cost of delegateERC721 uint128 private constant _BASE_OWNERSHIP_UPDATE_COST = 60_000; // worst case cost of transferFrom uint128 private constant _INCREMENTAL_OWNERSHIP_UPDATE_COST = 50_000; // incremental cost of transferFrom uint32 private constant _BASE_READ_RETURN_DATA_SIZE = 224; // 32 bytes for collection address, 64 bytes for each array uint32 private constant _READ_SIZE_INCREMENT_PER_UPDATE = 96; // One element in each of three arrays (staleOwner, newOwner, tokenId) uint32 private constant _EXT_CALL_GAS = 2_600; uint256 private constant _READ_TIMEOUT = 30 minutes; // Limit the gas allocation for lzReceive to prevent DOS issues uint128 private constant _LZ_RECEIVE_MAX_GAS_ALLOCATION = 8_000_000; // the address of the punk721 contract address public constant CRYPTOPUNKS721_ADDRESS = 0x000000000000003607fce1aC9e043a86675C5C2F; // The role for the collection registrar bytes32 public constant COLLECTION_REGISTRAR_ROLE = keccak256("COLLECTION_REGISTRAR_ROLE"); // The necessary delegate rights for the shadow token bytes32 private constant _GLOBAL_RIGHTS_WITH_MAX_EXPIRY = bytes32(uint256(type(uint40).max)); bytes24 public immutable SHADOW_TOKEN_RIGHTS; // The endpoint ID of this contract uint32 public immutable THIS_CONTRACT_EID; // The address of the exclusive delegate resolver address public immutable EXCLUSIVE_DELEGATE_RESOLVER_ADDRESS; // the address of the delegate registry address public immutable DELEGATE_REGISTRY_ADDRESS; // The address of the punk adapter, only applicable on mainnet address public punkAdapter; // The read channel ID uint32 public readChannel; // Single mapping for all collection configuration mapping(address baseCollectionAddress => CollectionConfig) public collectionConfigs; mapping(address shadowCollectionAddress => address baseCollectionAddress) private _shadowToBase; // Tracks delegated ownership for native collections mapping(address collection => mapping(uint256 tokenId => address delegatedOwner)) public delegatedOwners; // Store the hash of messages that failed to execute mapping(uint32 => mapping(bytes32 => mapping(uint64 => bytes32))) public payloadHashes; // Mapping of allowed executors, enforced if enforceExecutors is true mapping(address executor => bool allowed) public allowedExecutors; // Mapping of init timestamps for each read request mapping(bytes32 guid => uint256 timestamp) public initTimestamps; // Enforce executors if true bool public enforceExecutors; // LZ static variables uint8 private constant _MAP_AND_REDUCE = 2; uint16 private constant _MSG_TYPE = 1; uint32 private constant _READ_CHANNEL_EID_THRESHOLD = 4294965694; // Mapping of required confirmations per EID LibMap.Uint32Map private _requiredConfirmations; /** * @notice Initializes the Beacon contract. * @param _endpointLocator The address of the LayerZero endpoint locator. * @param _delegate The address allowed to set LZ configuration for this contract. * @param _readChannel The ID of the read channel. * @param _delegatexyz The address of the delegate registry. * @param _exclusiveDelegateResolver The address of the exclusive delegate resolver. */ constructor( address _endpointLocator, address _delegate, uint32 _readChannel, address _delegatexyz, address _exclusiveDelegateResolver ) OAppRead(ILayerZeroEndpointLocator(_endpointLocator).endpoint(), _delegate) Ownable(tx.origin) { if (_readChannel <= _READ_CHANNEL_EID_THRESHOLD) revert InvalidReadChannel(); EXCLUSIVE_DELEGATE_RESOLVER_ADDRESS = _exclusiveDelegateResolver; DELEGATE_REGISTRY_ADDRESS = _delegatexyz; SHADOW_TOKEN_RIGHTS = bytes24(keccak256(abi.encode(block.chainid))); THIS_CONTRACT_EID = ILayerZeroEndpointV2(ILayerZeroEndpointLocator(_endpointLocator).endpoint()).eid(); readChannel = _readChannel; _grantRole(COLLECTION_REGISTRAR_ROLE, tx.origin); _grantRole(DEFAULT_ADMIN_ROLE, tx.origin); _setPeer(readChannel, address(this).toBytes32()); } /** * @notice Register a collection (either native or shadow). * @param shadowCollectionAddress The address of the collection to register. * @param baseCollectionChainId The chain ID of the base collection. * @param baseCollectionAddress The address of the base collection. * @param baseCollectionEid The endpoint ID of the base collection. * @param baseCollectionPerNftOwnershipUpdateCost The cost of updating the ownership of an NFT. Set to 0 to use Beacon's default. * @dev If the collection is native: * - baseCollectionChainId must match block.chainid * - baseCollectionEid must match THIS_CONTRACT_EID * - baseCollectionAddress must match shadowCollectionAddress */ function registerCollection( address shadowCollectionAddress, uint32 baseCollectionChainId, address baseCollectionAddress, uint32 baseCollectionEid, uint32 baseCollectionPerNftOwnershipUpdateCost ) external onlyRole(COLLECTION_REGISTRAR_ROLE) { _validateCollectionConfiguration( shadowCollectionAddress, baseCollectionAddress, baseCollectionChainId, baseCollectionEid, baseCollectionPerNftOwnershipUpdateCost ); _shadowToBase[shadowCollectionAddress] = baseCollectionAddress; collectionConfigs[baseCollectionAddress] = CollectionConfig({ baseCollectionChainId: baseCollectionChainId, baseCollectionEid: baseCollectionEid, shadowAddress: shadowCollectionAddress, baseCollectionPerNftOwnershipUpdateCost: baseCollectionPerNftOwnershipUpdateCost }); emit CollectionRegistered(shadowCollectionAddress, baseCollectionAddress, baseCollectionEid); } function registerPunkAdapter(address _punkAdapter) external onlyOwner { if (block.chainid != 1) revert InvalidChain(); if (punkAdapter != address(0)) revert PunkAdapterAlreadySet(); punkAdapter = _punkAdapter; // approve punk adapter for all punk721 tokens IERC721(CRYPTOPUNKS721_ADDRESS).setApprovalForAll(_punkAdapter, true); emit PunkAdapterSet(_punkAdapter); } /** * @notice Trigger an ownership update for a collection. * @param baseCollectionAddress The address on this chain of the collection to update. * @param eids The array of endpoint IDs to try reading ownership from. At max, one will return a valid response. * @param tokenIds The array of token IDs to update ownership for. * @param refundRecipient The address to refund the excess LZ fee to, if any exists. * @param supplementalGasLimit The gas limit for the callback. */ function read( address baseCollectionAddress, uint256[] calldata tokenIds, uint32[] calldata eids, address refundRecipient, uint128 supplementalGasLimit ) external payable returns (bytes32) { if (tokenIds.length == 0 || eids.length == 0) revert ZeroLengthArray(); CollectionConfig storage config = collectionConfigs[baseCollectionAddress]; address shadowCollectionAddress = config.shadowAddress; if (shadowCollectionAddress == address(0)) revert ContractNotConfigured(); if (!_collectionIsNative(config) && !INFTShadow(shadowCollectionAddress).shadowModeEnabled()) { revert CollectionNotInShadowMode(); } bytes memory cmd = _buildCmd(baseCollectionAddress, eids, tokenIds); bytes memory options = this.combineOptions( readChannel, _MSG_TYPE, getReadOptions(baseCollectionAddress, tokenIds, supplementalGasLimit) ); MessagingReceipt memory receipt = _lzSend( readChannel, cmd, options, MessagingFee({nativeFee: msg.value, lzTokenFee: 0}), payable(refundRecipient) ); bytes32 guid = receipt.guid; initTimestamps[guid] = block.timestamp; emit ReadTriggered(baseCollectionAddress, shadowCollectionAddress, eids, tokenIds); return guid; } /** * @notice Releases tokens on a specific eid. * @param dstEid The endpoint ID to release the tokens on. * @param baseCollectionAddress The address of the base collection to release the tokens for. * @param tokenIds The array of token IDs to release. * @param beneficiary The address to receive the tokens. * @param refundRecipient The address to refund the excess LZ fee to, if any exists. * @notice should be triggered by the shadow contract, calls from EOAs for contracts that are not configured will revert */ function send( uint32 dstEid, address baseCollectionAddress, uint256[] calldata tokenIds, address beneficiary, address refundRecipient, uint128 supplementalGasLimit ) external payable { if (beneficiary == address(0)) revert BeneficiaryZeroAddress(); if (dstEid == THIS_CONTRACT_EID || dstEid > _READ_CHANNEL_EID_THRESHOLD) revert InvalidEid(); if (tokenIds.length == 0) revert ZeroLengthArray(); CollectionConfig storage config = collectionConfigs[baseCollectionAddress]; address shadowCollectionAddress = config.shadowAddress; bool isNative = _collectionIsNative(config); if (isNative) { for (uint256 i = 0; i < tokenIds.length; i++) { uint256 tokenId = tokenIds[i]; // if the collection is native, the caller must be the owner (enforced by transferring from msg.sender) IERC721(shadowCollectionAddress).transferFrom(msg.sender, address(this), tokenId); } } else { // if the collection is not native, the Shadow must be the caller (Shadow should enforce that the caller is approved or the owner) if (msg.sender != shadowCollectionAddress) revert InvalidCaller(); } bytes memory payload = abi.encode(baseCollectionAddress, beneficiary, tokenIds); bytes memory options = this.combineOptions( dstEid, _MSG_TYPE, getSendOptions(dstEid, baseCollectionAddress, tokenIds, supplementalGasLimit) ); _lzSend(dstEid, payload, options, MessagingFee({nativeFee: msg.value, lzTokenFee: 0}), payable(refundRecipient)); emit Sent(dstEid, baseCollectionAddress, shadowCollectionAddress, tokenIds, beneficiary); } function executeMessage(Origin calldata _origin, bytes32 guid, bytes calldata _message) external { if (msg.sender != address(this)) revert OnlyInternalCalls(); _executeMessage(_origin, guid, _message); } /** * @notice Set whether to enforce executors. * @param _enforceExecutors Whether to enforce executors. */ function setEnforceExecutors(bool _enforceExecutors) external onlyOwner { enforceExecutors = _enforceExecutors; emit EnforceExecutionSet(_enforceExecutors); } /** * @notice Set whether an executor is allowed. * @param executor The address of the executor. * @param allowed Whether the executor is allowed. */ function setAllowedExecutor(address executor, bool allowed) external onlyOwner { allowedExecutors[executor] = allowed; emit AllowedExecutorSet(executor, allowed); } /** * @notice Set the required confirmations for a read request on an EID. * @param eid The endpoint ID to set the required confirmations for. * @param confirmations The required confirmations. */ function setRequiredConfirmations(uint32 eid, uint16 confirmations) external onlyOwner { _requiredConfirmations.set(eid, confirmations); emit RequiredConfirmationsSet(eid, confirmations); } /** * @notice sets the base collection per nft ownership update cost * @param baseCollectionAddress The address of the base collection. * @param cost The cost of updating the ownership of an NFT. */ function setBaseCollectionPerNftOwnershipUpdateCost(address baseCollectionAddress, uint32 cost) external onlyOwner { collectionConfigs[baseCollectionAddress].baseCollectionPerNftOwnershipUpdateCost = cost; } /** * @notice Set the read channel for the Beacon. * @param _readChannel The new read channel. */ function setReadChannel(uint32 _readChannel) external onlyOwner { if (_readChannel <= _READ_CHANNEL_EID_THRESHOLD) revert InvalidReadChannel(); readChannel = _readChannel; emit ReadChannelSet(_readChannel); } /** * @notice Get the required confirmations for a read request on an EID. * @param eid The endpoint ID to get the required confirmations for. * @return uint32 The required confirmations. */ function requiredConfirmations(uint32 eid) external view returns (uint16) { return uint16(_requiredConfirmations.get(eid)); } /** * @notice Get the base collection address for a given shadow collection address. * @param shadowCollectionAddress The address of the shadow collection. * @return address the base collection address. */ function shadowToBase(address shadowCollectionAddress) external view returns (address) { return _shadowToBase[shadowCollectionAddress]; } /** * @notice Get the shadow collection address for a given base collection address. * @param baseCollectionAddress The address of the base collection. * @return address the shadow collection address. */ function baseToShadow(address baseCollectionAddress) external view returns (address) { return collectionConfigs[baseCollectionAddress].shadowAddress; } /** * @notice Calculate fees for sending a read request for an array of token IDs. * @param baseCollectionAddress The address of the collection to calculate fees for. * @param tokenIds The array of token IDs to calculate fees for. * @param dstEids The array of endpoint IDs to calculate fees for. * @param supplementalGasLimit The gas limit for the callback. * @return nativeFee The native fee for the message. * @return lzTokenFee The LZ token fee for the message. * @dev the shadow contract has a variant with built in options to simplify. */ function quoteRead( address baseCollectionAddress, uint256[] calldata tokenIds, uint32[] calldata dstEids, uint128 supplementalGasLimit ) external view returns (uint256 nativeFee, uint256 lzTokenFee) { CollectionConfig storage config = collectionConfigs[baseCollectionAddress]; address shadowCollectionAddress = config.shadowAddress; if (shadowCollectionAddress == address(0)) revert ContractNotConfigured(); bytes memory cmd = _buildCmd(shadowCollectionAddress, dstEids, tokenIds); bytes memory options = this.combineOptions( readChannel, _MSG_TYPE, getReadOptions(baseCollectionAddress, tokenIds, supplementalGasLimit) ); MessagingFee memory fee = _quote(readChannel, cmd, options, false); return (fee.nativeFee, fee.lzTokenFee); } /** * @notice Calculate fees for sending a message to the shadow contract. * @param dstEid The endpoint ID to send the message to. * @param baseCollectionAddress The address of the collection to calculate fees for. * @param tokenIds The array of token IDs to calculate fees for. * @return nativeFee The native fee for the message. * @return lzTokenFee The LZ token fee for the message. * @dev the shadow contract has a variant with built in options to simplify. */ function quoteSend( uint32 dstEid, address baseCollectionAddress, uint256[] calldata tokenIds, uint128 supplementalGasLimit ) external view returns (uint256 nativeFee, uint256 lzTokenFee) { CollectionConfig storage config = collectionConfigs[baseCollectionAddress]; address shadowCollectionAddress = config.shadowAddress; if (shadowCollectionAddress == address(0)) revert ContractNotConfigured(); bytes memory payload = abi.encode(baseCollectionAddress, address(0), tokenIds); bytes memory options = this.combineOptions( dstEid, _MSG_TYPE, getSendOptions(dstEid, baseCollectionAddress, tokenIds, supplementalGasLimit) ); MessagingFee memory fee = _quote(dstEid, payload, options, false); return (fee.nativeFee, fee.lzTokenFee); } /** * @notice Fetch the owner of a token from the delegate resolver. * @param baseCollectionAddress The address of the collection to fetch the owner for. * @param tokenId The ID of the token to fetch the owner for. * @return _owner the owner of the token. * @return _isLocked true if the token is locked, false otherwise. * @dev reverts if the contract is not configured or the token is locked. */ function unlockedExclusiveOwnerByRights(address baseCollectionAddress, uint256 tokenId) external view returns (address _owner, bool _isLocked) { CollectionConfig memory config = collectionConfigs[baseCollectionAddress]; if (config.baseCollectionEid == 0) return (address(0), true); bool isNative = config.baseCollectionChainId == block.chainid; address shadowCollectionAddress = config.shadowAddress; address _baseOwner; if (isNative) { try IERC721(shadowCollectionAddress).ownerOf(tokenId) returns (address owner) { if (owner == address(this)) { return (address(this), true); } else { _baseOwner = owner; } } catch { // if the token does not exist in a native collection, we can preemptively return address(0) as the owner return (address(0), false); } } else { // if collection is not configured or the token is locked, return _isLocked = true to render it a no-op if (shadowCollectionAddress == address(0) || INFTShadow(shadowCollectionAddress).locked(tokenId)) { return (address(0), true); } else { try INFTShadow(shadowCollectionAddress).ownerOf(tokenId) returns (address owner) { _baseOwner = owner; } catch { // if the token does not exist for an unlocked shadow, the token was burned _baseOwner = address(0); } } } // otherwise, we return the exclusive owner by rights according to the delegate resolver try IExclusiveDelegateResolver(EXCLUSIVE_DELEGATE_RESOLVER_ADDRESS).exclusiveOwnerByRights( shadowCollectionAddress, tokenId, SHADOW_TOKEN_RIGHTS ) returns (address owner) { return (owner, false); } catch { return (_baseOwner, false); } } /** * @notice Processes individual NFT ownership responses for consumption by lzReduce. * @param _request The original read request data. * @param _response The response from the ownership query (encoded address, bool) * @return bytes memory encoded (staleOwner, newOwner, tokenId) */ function lzMap(bytes calldata _request, bytes calldata _response) external view override returns (bytes memory) { (address collectionAddress, uint256 tokenId) = abi.decode(_request[46:110], (address, uint256)); address staleOwner; (address newOwner, bool isLocked) = abi.decode(_response, (address, bool)); if (isLocked) return new bytes(0); CollectionConfig memory config = collectionConfigs[collectionAddress]; if (_collectionIsNative(config)) { // For native collections, read from delegation mapping staleOwner = delegatedOwners[collectionAddress][tokenId]; } else { // For shadow collections, read from the shadow contract try INFTShadow(config.shadowAddress).ownerOf(tokenId) returns (address owner) { staleOwner = owner; } catch { // ownerOf reverts if the token does not exist staleOwner = address(0); } } return abi.encode(staleOwner, newOwner, tokenId); } /** * @notice Reduces the response from the ownership query post lzMap * @param _responses An array of abi encoded (staleOwner, newOwner, tokenId) * @return bytes memory encoded (collectionAddress, staleOwners, newOwners, tokenIds) */ function lzReduce(bytes calldata _request, bytes[] calldata _responses) external view override returns (bytes memory) { address collectionAddress = address(bytes20(_request[64:84])); CollectionConfig memory config = collectionConfigs[collectionAddress]; address targetAddress = config.shadowAddress; address[] memory staleOwners = new address[](_responses.length); address[] memory newOwners = new address[](_responses.length); uint256[] memory tokenIds = new uint256[](_responses.length); uint256 updateCount = 0; for (uint256 i = 0; i < _responses.length; i++) { if (_responses[i].length == 0) { // lzMap returns empty bytes if ownership data is not available continue; } (staleOwners[i], newOwners[i], tokenIds[i]) = abi.decode(_responses[i], (address, address, uint256)); if (staleOwners[i] != newOwners[i]) { tokenIds[updateCount] = tokenIds[i]; staleOwners[updateCount] = staleOwners[i]; newOwners[updateCount] = newOwners[i]; unchecked { ++updateCount; } } } // if updateCount is less than the length of the tokenIds array, we need to resize the arrays if (updateCount < tokenIds.length) { address[] memory resizedStaleOwners = new address[](updateCount); address[] memory resizedNewOwners = new address[](updateCount); uint256[] memory resizedTokenIds = new uint256[](updateCount); for (uint256 i = 0; i < updateCount; i++) { resizedStaleOwners[i] = staleOwners[i]; resizedNewOwners[i] = newOwners[i]; resizedTokenIds[i] = tokenIds[i]; } return abi.encode(targetAddress, resizedStaleOwners, resizedNewOwners, resizedTokenIds); } return abi.encode(targetAddress, staleOwners, newOwners, tokenIds); } /** * @notice Generates options for a send operation. * @param dstEid The endpoint ID to send the message to. * @param baseCollectionAddress The address of the base collection. * @param tokenIds The array of token IDs. * @param supplementalGasLimit The gas limit for the send operation. * @return options The options bytes. */ function getSendOptions( uint32 dstEid, address baseCollectionAddress, uint256[] calldata tokenIds, uint128 supplementalGasLimit ) public view returns (bytes memory) { CollectionConfig memory config = collectionConfigs[baseCollectionAddress]; bool targetIsNative = config.baseCollectionEid == dstEid; uint128 totalGasRequired = _calculateLzReceiveGasAllocation( config.baseCollectionPerNftOwnershipUpdateCost, supplementalGasLimit, tokenIds.length, targetIsNative, false ); return OptionsBuilder.newOptions().addExecutorLzReceiveOption(totalGasRequired, 0); } /** * @notice Generates options for a read operation. * @param baseCollectionAddress The address of the base collection. * @param tokenIds The array of token IDs. * @return options The options bytes. */ function getReadOptions(address baseCollectionAddress, uint256[] calldata tokenIds, uint128 supplementalGasLimit) public view returns (bytes memory) { CollectionConfig memory config = collectionConfigs[baseCollectionAddress]; bool isNative = config.baseCollectionChainId == block.chainid; uint128 totalGasRequired = _calculateLzReceiveGasAllocation( config.baseCollectionPerNftOwnershipUpdateCost, supplementalGasLimit, tokenIds.length, isNative, true ); uint32 totalReturnDataSize = _BASE_READ_RETURN_DATA_SIZE + (_READ_SIZE_INCREMENT_PER_UPDATE * uint32(tokenIds.length)); bytes memory options = OptionsBuilder.newOptions().addExecutorLzReadOption(totalGasRequired, totalReturnDataSize, 0); return options; } /** * @notice Handle incoming messages from LayerZero. * @dev the message type is determined by the srcEid. * @dev read responses will update the ownership of the tokens. * @dev traditional LZ messages will update the lock state of the tokens. */ function _lzReceive( Origin calldata _origin, bytes32 guid, bytes calldata _message, address executor, bytes calldata /* _extraData */ ) internal override { if (enforceExecutors && !allowedExecutors[executor]) revert UnauthorizedExecutor(); // Prepare the execution calldata bytes memory callData = abi.encodeWithSelector(this.executeMessage.selector, _origin, guid, _message); // Calculate gas to forward, leaving some in reserve uint256 externalGas = gasleft() - _SAFE_CALL_BUFFER; // Use SafeCall to execute with gas limit and capture return data (bool success, bytes memory reason) = address(this).safeCall(externalGas, 0, 4, callData); if (!success) { // Cache failed message hash bytes32 payloadHash = keccak256(abi.encodePacked(address(this), callData, block.chainid)); payloadHashes[_origin.srcEid][_origin.sender][_origin.nonce] = payloadHash; emit MessageCached(_origin.srcEid, _origin.sender, _origin.nonce, reason); } } /** * @notice Retry a failed message. * @param srcEid The source endpoint ID. * @param sender The sender of the message. * @param nonce The nonce of the message. * @param origin The original origin of the message. * @param message The message to retry. * @dev only allow retries for EIDs under the read channel threshold * @dev the consequence for failed reads is low enough that we can just retry */ function retryFailedMessage( uint32 srcEid, bytes32 sender, uint64 nonce, Origin calldata origin, bytes32 guid, bytes calldata message ) external { // only allow retries for EIDs under the read channel threshold if (srcEid > _READ_CHANNEL_EID_THRESHOLD) revert InvalidEid(); // Prepare calldata and verify hash bytes memory callData = abi.encodeWithSelector(this.executeMessage.selector, origin, guid, message); bytes32 payloadHash = keccak256(abi.encodePacked(address(this), callData, block.chainid)); if (payloadHashes[srcEid][sender][nonce] != payloadHash) revert InvalidPayloadHash(); // Clear cache before execution delete payloadHashes[srcEid][sender][nonce]; // Execute with SafeCall, using all remaining gas // limit return data to 4 bytes, it will either be a custom error with no data, or nothing (bool success, bytes memory reason) = address(this).safeCall(gasleft(), 0, 4, callData); if (!success) { // If retry fails, revert with the reason assembly { revert(add(32, reason), mload(reason)) } } emit CachedMessageExecuted(srcEid, sender, nonce); } function _executeMessage(Origin calldata _origin, bytes32 guid, bytes calldata _message) internal { if (_origin.srcEid > _READ_CHANNEL_EID_THRESHOLD) { if (block.timestamp - initTimestamps[guid] > _READ_TIMEOUT) revert StaleReadRequest(); // Handle lzRead responses _updateOwnership(_message, guid); } else { // Handle standard LayerZero messages. _updateLockState(_message); } } function _updateOwnership(bytes calldata _message, bytes32 guid) internal { (address shadowAddress, address[] memory staleOwners, address[] memory newOwners, uint256[] memory tokenIds) = abi.decode(_message, (address, address[], address[], uint256[])); address baseCollectionAddress = _shadowToBase[shadowAddress]; CollectionConfig memory config = collectionConfigs[baseCollectionAddress]; bool isNative = _collectionIsNative(config); // For shadow collections, use the shadow contract INFTShadow _shadow = INFTShadow(shadowAddress); if (isNative) { // For native collections, update the delegated ownership _updateDelegations(baseCollectionAddress, newOwners, tokenIds); } else { for (uint256 i = 0; i < tokenIds.length; i++) { address staleOwner = staleOwners[i]; address newOwner = newOwners[i]; uint256 tokenId = tokenIds[i]; if (staleOwner == address(0)) { (bool success,) = address(_shadow).call(abi.encodeWithSignature("mint(address,uint256)", newOwner, tokenId)); if (!success) revert MintFailed(); } else if (newOwner == address(0)) { (bool success,) = address(_shadow).call(abi.encodeWithSignature("burn(uint256)", tokenId)); if (!success) revert BurnFailed(); } else { (bool success,) = address(_shadow).call( abi.encodeWithSignature("transferFrom(address,address,uint256)", staleOwner, newOwner, tokenId) ); if (!success) revert TransferFailed(); } } _shadow.executeCallback(guid); } } function _updateLockState(bytes calldata _message) internal { (address collectionAddress, address beneficiary, uint256[] memory tokenIds) = abi.decode(_message, (address, address, uint256[])); CollectionConfig storage config = collectionConfigs[collectionAddress]; if (config.shadowAddress == address(0)) revert ContractNotConfigured(); bool isNative = config.baseCollectionChainId == block.chainid; if (isNative) { // Handle standard LayerZero messages. _clearDelegationsAndReleaseTokens(collectionAddress, beneficiary, tokenIds); } else { // For shadow collections, unlock tokens in the shadow contract (bool success,) = address(INFTShadow(config.shadowAddress)).call( abi.encodeWithSignature("unlockTokens(uint256[],address)", tokenIds, beneficiary) ); if (!success) revert UnlockFailed(); } } /** * @notice Build the command for a read request. * @param targetCollectionAddress The address on the target chain to read from. * @param eids The array of endpoint IDs to build the command for. * @param tokenIds The array of token IDs to build the command for. * @return bytes memory The built command. */ function _buildCmd(address targetCollectionAddress, uint32[] calldata eids, uint256[] calldata tokenIds) internal view returns (bytes memory) { // Construct the call to the beacon on peer eid to fetch ownership from that eid's exclusive delegate resolver EVMCallRequestV1[] memory readRequests = new EVMCallRequestV1[](tokenIds.length * eids.length); for (uint256 i = 0; i < tokenIds.length; i++) { for (uint256 j = 0; j < eids.length; j++) { uint32 confirmations = _requiredConfirmations.get(eids[j]); if (confirmations == 0) revert InvalidEid(); readRequests[i * eids.length + j] = EVMCallRequestV1({ appRequestLabel: uint16(i + 1 + j * tokenIds.length), targetEid: eids[j], isBlockNum: false, blockNumOrTimestamp: uint64(block.timestamp), confirmations: uint16(confirmations), to: _getPeerOrRevert(eids[j]).toAddress(), callData: abi.encodeWithSelector( this.unlockedExclusiveOwnerByRights.selector, targetCollectionAddress, tokenIds[i] ) }); } } EVMCallComputeV1 memory computeSettings = EVMCallComputeV1(_MAP_AND_REDUCE, THIS_CONTRACT_EID, false, uint64(block.timestamp), 0, address(this)); return ReadCodecV1.encode(0, readRequests, computeSettings); } /** * @notice Updates the delegations based on the received message. * @param collectionAddress The address of the collection. * @param newOwners The array of new owners. * @param tokenIds The array of token IDs. */ function _updateDelegations(address collectionAddress, address[] memory newOwners, uint256[] memory tokenIds) internal { bytes[] memory multicallRawData = new bytes[](tokenIds.length * 2); uint256 multicallDataLength = 0; address nftContractToDelegate = collectionAddress == punkAdapter ? CRYPTOPUNKS721_ADDRESS : collectionAddress; for (uint256 i = 0; i < tokenIds.length; ++i) { address newOwner = newOwners[i]; uint256 tokenId = tokenIds[i]; address staleOwner = delegatedOwners[collectionAddress][tokenId]; if (IERC721(collectionAddress).ownerOf(tokenId) != address(this)) { revert InvalidOwner(); } if (staleOwner != address(0)) { multicallRawData[multicallDataLength] = abi.encodeWithSelector( IDelegateRegistry.delegateERC721.selector, staleOwner, nftContractToDelegate, tokenId, _GLOBAL_RIGHTS_WITH_MAX_EXPIRY, false ); unchecked { ++multicallDataLength; } } multicallRawData[multicallDataLength] = abi.encodeWithSelector( IDelegateRegistry.delegateERC721.selector, newOwner, nftContractToDelegate, tokenId, _GLOBAL_RIGHTS_WITH_MAX_EXPIRY, true ); unchecked { ++multicallDataLength; } delegatedOwners[collectionAddress][tokenId] = newOwner; } bytes[] memory multicallData = new bytes[](multicallDataLength); for (uint256 i = 0; i < multicallDataLength; ++i) { multicallData[i] = multicallRawData[i]; } IDelegateRegistry(DELEGATE_REGISTRY_ADDRESS).multicall(multicallData); } /** * @notice Clears the delegations and releases the tokens. * @param collectionAddress The address of the collection. * @param beneficiary The address of the beneficiary. * @param tokenIds The array of token IDs. */ function _clearDelegationsAndReleaseTokens( address collectionAddress, address beneficiary, uint256[] memory tokenIds ) internal { for (uint256 i = 0; i < tokenIds.length; ++i) { IERC721(collectionAddress).transferFrom(address(this), beneficiary, tokenIds[i]); } _clearDelegations(collectionAddress, tokenIds); } /** * @notice Clears the delegations. * @param collectionAddress The address of the collection. * @param tokenIds The array of token IDs. */ function _clearDelegations(address collectionAddress, uint256[] memory tokenIds) internal { bytes[] memory multicallData = new bytes[](tokenIds.length); address nftContractToDelegate = collectionAddress == punkAdapter ? CRYPTOPUNKS721_ADDRESS : collectionAddress; for (uint256 i = 0; i < tokenIds.length; ++i) { uint256 tokenId = tokenIds[i]; multicallData[i] = abi.encodeWithSelector( IDelegateRegistry.delegateERC721.selector, delegatedOwners[collectionAddress][tokenId], nftContractToDelegate, tokenId, _GLOBAL_RIGHTS_WITH_MAX_EXPIRY, false ); delegatedOwners[collectionAddress][tokenId] = address(0); } IDelegateRegistry(DELEGATE_REGISTRY_ADDRESS).multicall(multicallData); } function _collectionIsNative(CollectionConfig memory config) internal view returns (bool) { if (config.baseCollectionChainId == 0) revert ContractNotConfigured(); return config.baseCollectionChainId == block.chainid; } function _validateCollectionConfiguration( address shadowCollectionAddress, address baseCollectionAddress, uint256 baseCollectionChainId, uint32 baseCollectionEid, uint128 baseCollectionPerNftOwnershipUpdateCost ) internal view { if (baseCollectionChainId == 0) revert InvalidChain(); if (baseCollectionEid == 0) revert InvalidEid(); if (baseCollectionAddress == address(0)) revert ZeroAddress(); if (shadowCollectionAddress == address(0)) revert ZeroAddress(); if (baseCollectionPerNftOwnershipUpdateCost > _LZ_RECEIVE_MAX_GAS_ALLOCATION) { revert MaxLzReceiveGasAllocationExceeded(); } bool isNative = baseCollectionChainId == block.chainid; if (isNative) { if (baseCollectionEid != THIS_CONTRACT_EID) revert InvalidEid(); if (shadowCollectionAddress != baseCollectionAddress) revert MismatchedCollectionAddress(); } else { if (baseCollectionEid == THIS_CONTRACT_EID) revert InvalidEid(); } if (collectionConfigs[baseCollectionAddress].shadowAddress != address(0)) revert CollectionAlreadyRegistered(); } function _calculateLzReceiveGasAllocation( uint128 baseCollectionPerNftOwnershipUpdateCost, uint128 supplementalGasLimit, uint256 tokenIdsLength, bool isNative, bool isRead ) internal pure returns (uint128 totalGasRequired) { if (isRead) { unchecked { uint128 baseUpdateCost = isNative ? uint128(_SAFE_CALL_BUFFER + _BASE_OWNERSHIP_UPDATE_COST) : _EXT_CALL_GAS + uint128(_SAFE_CALL_BUFFER + _BASE_OWNERSHIP_UPDATE_COST); uint128 incrementalUpdateCost = isNative ? _DELEGATION_UPDATE_COST * 2 : _INCREMENTAL_OWNERSHIP_UPDATE_COST; totalGasRequired = baseUpdateCost + incrementalUpdateCost * uint128(tokenIdsLength); } } else { unchecked { uint128 nftOwnershipUpdateCost = isNative && baseCollectionPerNftOwnershipUpdateCost != 0 ? baseCollectionPerNftOwnershipUpdateCost : _INCREMENTAL_OWNERSHIP_UPDATE_COST; uint128 perNftCost = isNative ? nftOwnershipUpdateCost + _DELEGATION_UPDATE_COST : nftOwnershipUpdateCost; totalGasRequired = uint128(_SAFE_CALL_BUFFER + _BASE_OWNERSHIP_UPDATE_COST + perNftCost * tokenIdsLength); } } totalGasRequired += supplementalGasLimit; if (totalGasRequired > _LZ_RECEIVE_MAX_GAS_ALLOCATION) revert MaxLzReceiveGasAllocationExceeded(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC-721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC-721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or * {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the address zero. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// 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.20; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; struct EVMCallRequestV1 { uint16 appRequestLabel; // Label identifying the application or type of request (can be use in lzCompute) uint32 targetEid; // Target endpoint ID (representing a target blockchain) bool isBlockNum; // True if the request = block number, false if timestamp uint64 blockNumOrTimestamp; // Block number or timestamp to use in the request uint16 confirmations; // Number of block confirmations on top of the requested block number or timestamp before the view function can be called address to; // Address of the target contract on the target chain bytes callData; // Calldata for the contract call } struct EVMCallComputeV1 { uint8 computeSetting; // Compute setting (0 = map only, 1 = reduce only, 2 = map reduce) uint32 targetEid; // Target endpoint ID (representing a target blockchain) bool isBlockNum; // True if the request = block number, false if timestamp uint64 blockNumOrTimestamp; // Block number or timestamp to use in the request uint16 confirmations; // Number of block confirmations on top of the requested block number or timestamp before the view function can be called address to; // Address of the target contract on the target chain } library ReadCodecV1 { using SafeCast for uint256; uint16 internal constant CMD_VERSION = 1; uint8 internal constant REQUEST_VERSION = 1; uint16 internal constant RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL = 1; uint8 internal constant COMPUTE_VERSION = 1; uint16 internal constant COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL = 1; error InvalidVersion(); error InvalidType(); function decode( bytes calldata _cmd ) internal pure returns (uint16 appCmdLabel, EVMCallRequestV1[] memory evmCallRequests, EVMCallComputeV1 memory compute) { uint256 offset = 0; uint16 cmdVersion = uint16(bytes2(_cmd[offset:offset + 2])); offset += 2; if (cmdVersion != CMD_VERSION) revert InvalidVersion(); appCmdLabel = uint16(bytes2(_cmd[offset:offset + 2])); offset += 2; (evmCallRequests, offset) = decodeRequestsV1(_cmd, offset); // decode the compute if it exists if (offset < _cmd.length) { (compute, ) = decodeEVMCallComputeV1(_cmd, offset); } } function decodeRequestsV1( bytes calldata _cmd, uint256 _offset ) internal pure returns (EVMCallRequestV1[] memory evmCallRequests, uint256 newOffset) { newOffset = _offset; uint16 requestCount = uint16(bytes2(_cmd[newOffset:newOffset + 2])); newOffset += 2; evmCallRequests = new EVMCallRequestV1[](requestCount); for (uint16 i = 0; i < requestCount; i++) { uint8 requestVersion = uint8(_cmd[newOffset]); newOffset += 1; if (requestVersion != REQUEST_VERSION) revert InvalidVersion(); uint16 appRequestLabel = uint16(bytes2(_cmd[newOffset:newOffset + 2])); newOffset += 2; uint16 resolverType = uint16(bytes2(_cmd[newOffset:newOffset + 2])); newOffset += 2; if (resolverType == RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL) { (EVMCallRequestV1 memory request, uint256 nextOffset) = decodeEVMCallRequestV1( _cmd, newOffset, appRequestLabel ); newOffset = nextOffset; evmCallRequests[i] = request; } else { revert InvalidType(); } } } function decodeEVMCallRequestV1( bytes calldata _cmd, uint256 _offset, uint16 _appRequestLabel ) internal pure returns (EVMCallRequestV1 memory request, uint256 newOffset) { newOffset = _offset; request.appRequestLabel = _appRequestLabel; uint16 requestSize = uint16(bytes2(_cmd[newOffset:newOffset + 2])); newOffset += 2; request.targetEid = uint32(bytes4(_cmd[newOffset:newOffset + 4])); newOffset += 4; request.isBlockNum = uint8(_cmd[newOffset]) == 1; newOffset += 1; request.blockNumOrTimestamp = uint64(bytes8(_cmd[newOffset:newOffset + 8])); newOffset += 8; request.confirmations = uint16(bytes2(_cmd[newOffset:newOffset + 2])); newOffset += 2; request.to = address(bytes20(_cmd[newOffset:newOffset + 20])); newOffset += 20; uint16 callDataSize = requestSize - 35; request.callData = _cmd[newOffset:newOffset + callDataSize]; newOffset += callDataSize; } function decodeEVMCallComputeV1( bytes calldata _cmd, uint256 _offset ) internal pure returns (EVMCallComputeV1 memory compute, uint256 newOffset) { newOffset = _offset; uint8 computeVersion = uint8(_cmd[newOffset]); newOffset += 1; if (computeVersion != COMPUTE_VERSION) revert InvalidVersion(); uint16 computeType = uint16(bytes2(_cmd[newOffset:newOffset + 2])); newOffset += 2; if (computeType != COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL) revert InvalidType(); compute.computeSetting = uint8(_cmd[newOffset]); newOffset += 1; compute.targetEid = uint32(bytes4(_cmd[newOffset:newOffset + 4])); newOffset += 4; compute.isBlockNum = uint8(_cmd[newOffset]) == 1; newOffset += 1; compute.blockNumOrTimestamp = uint64(bytes8(_cmd[newOffset:newOffset + 8])); newOffset += 8; compute.confirmations = uint16(bytes2(_cmd[newOffset:newOffset + 2])); newOffset += 2; compute.to = address(bytes20(_cmd[newOffset:newOffset + 20])); newOffset += 20; } function decodeCmdAppLabel(bytes calldata _cmd) internal pure returns (uint16) { uint256 offset = 0; uint16 cmdVersion = uint16(bytes2(_cmd[offset:offset + 2])); offset += 2; if (cmdVersion != CMD_VERSION) revert InvalidVersion(); return uint16(bytes2(_cmd[offset:offset + 2])); } function decodeRequestV1AppRequestLabel(bytes calldata _request) internal pure returns (uint16) { uint256 offset = 0; uint8 requestVersion = uint8(_request[offset]); offset += 1; if (requestVersion != REQUEST_VERSION) revert InvalidVersion(); return uint16(bytes2(_request[offset:offset + 2])); } function encode( uint16 _appCmdLabel, EVMCallRequestV1[] memory _evmCallRequests, EVMCallComputeV1 memory _evmCallCompute ) internal pure returns (bytes memory) { bytes memory cmd = encode(_appCmdLabel, _evmCallRequests); if (_evmCallCompute.targetEid != 0) { // if eid is 0, it means no compute cmd = appendEVMCallComputeV1(cmd, _evmCallCompute); } return cmd; } function encode( uint16 _appCmdLabel, EVMCallRequestV1[] memory _evmCallRequests ) internal pure returns (bytes memory) { bytes memory cmd = abi.encodePacked(CMD_VERSION, _appCmdLabel, _evmCallRequests.length.toUint16()); for (uint256 i = 0; i < _evmCallRequests.length; i++) { cmd = appendEVMCallRequestV1(cmd, _evmCallRequests[i]); } return cmd; } // todo: optimize this with Buffer function appendEVMCallRequestV1( bytes memory _cmd, EVMCallRequestV1 memory _request ) internal pure returns (bytes memory) { bytes memory newCmd = abi.encodePacked( _cmd, REQUEST_VERSION, _request.appRequestLabel, RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL, (_request.callData.length + 35).toUint16(), _request.targetEid ); return abi.encodePacked( newCmd, _request.isBlockNum, _request.blockNumOrTimestamp, _request.confirmations, _request.to, _request.callData ); } function appendEVMCallComputeV1( bytes memory _cmd, EVMCallComputeV1 memory _compute ) internal pure returns (bytes memory) { return abi.encodePacked( _cmd, COMPUTE_VERSION, COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL, _compute.computeSetting, _compute.targetEid, _compute.isBlockNum, _compute.blockNumOrTimestamp, _compute.confirmations, _compute.to ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { AddressCast } from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol"; import { OApp } from "./OApp.sol"; abstract contract OAppRead is OApp { constructor(address _endpoint, address _delegate) OApp(_endpoint, _delegate) {} // ------------------------------- // Only Owner function setReadChannel(uint32 _channelId, bool _active) public virtual onlyOwner { _setPeer(_channelId, _active ? AddressCast.toBytes32(address(this)) : bytes32(0)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IOAppOptionsType3, EnforcedOptionParam } from "../interfaces/IOAppOptionsType3.sol"; /** * @title OAppOptionsType3 * @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options. */ abstract contract OAppOptionsType3 is IOAppOptionsType3, Ownable { uint16 internal constant OPTION_TYPE_3 = 3; // @dev The "msgType" should be defined in the child contract. mapping(uint32 eid => mapping(uint16 msgType => bytes enforcedOption)) public enforcedOptions; /** * @dev Sets the enforced options for specific endpoint and message type combinations. * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options. * * @dev Only the owner/admin of the OApp can call this function. * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc. * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType. * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose(). */ function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner { _setEnforcedOptions(_enforcedOptions); } /** * @dev Sets the enforced options for specific endpoint and message type combinations. * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options. * * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc. * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType. * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose(). */ function _setEnforcedOptions(EnforcedOptionParam[] memory _enforcedOptions) internal virtual { for (uint256 i = 0; i < _enforcedOptions.length; i++) { // @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining. _assertOptionsType3(_enforcedOptions[i].options); enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options; } emit EnforcedOptionSet(_enforcedOptions); } /** * @notice Combines options for a given endpoint and message type. * @param _eid The endpoint ID. * @param _msgType The OAPP message type. * @param _extraOptions Additional options passed by the caller. * @return options The combination of caller specified options AND enforced options. * * @dev If there is an enforced lzReceive option: * - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether} * - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function. * @dev This presence of duplicated options is handled off-chain in the verifier/executor. */ function combineOptions( uint32 _eid, uint16 _msgType, bytes calldata _extraOptions ) public view virtual returns (bytes memory) { bytes memory enforced = enforcedOptions[_eid][_msgType]; // No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options. if (enforced.length == 0) return _extraOptions; // No caller options, return enforced if (_extraOptions.length == 0) return enforced; // @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined. if (_extraOptions.length >= 2) { _assertOptionsType3(_extraOptions); // @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced. return bytes.concat(enforced, _extraOptions[2:]); } // No valid set of options was found. revert InvalidOptions(_extraOptions); } /** * @dev Internal function to assert that options are of type 3. * @param _options The options to be checked. */ function _assertOptionsType3(bytes memory _options) internal pure virtual { uint16 optionsType; assembly { optionsType := mload(add(_options, 2)) } if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { BytesLib } from "solidity-bytes-utils/contracts/BytesLib.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import { ExecutorOptions } from "@layerzerolabs/lz-evm-messagelib-v2/contracts/libs/ExecutorOptions.sol"; import { DVNOptions } from "@layerzerolabs/lz-evm-messagelib-v2/contracts/uln/libs/DVNOptions.sol"; /** * @title OptionsBuilder * @dev Library for building and encoding various message options. */ library OptionsBuilder { using SafeCast for uint256; using BytesLib for bytes; // Constants for options types uint16 internal constant TYPE_1 = 1; // legacy options type 1 uint16 internal constant TYPE_2 = 2; // legacy options type 2 uint16 internal constant TYPE_3 = 3; // Custom error message error InvalidSize(uint256 max, uint256 actual); error InvalidOptionType(uint16 optionType); // Modifier to ensure only options of type 3 are used modifier onlyType3(bytes memory _options) { if (_options.toUint16(0) != TYPE_3) revert InvalidOptionType(_options.toUint16(0)); _; } /** * @dev Creates a new options container with type 3. * @return options The newly created options container. */ function newOptions() internal pure returns (bytes memory) { return abi.encodePacked(TYPE_3); } /** * @dev Adds an executor LZ receive option to the existing options. * @param _options The existing options container. * @param _gas The gasLimit used on the lzReceive() function in the OApp. * @param _value The msg.value passed to the lzReceive() function in the OApp. * @return options The updated options container. * * @dev When multiples of this option are added, they are summed by the executor * eg. if (_gas: 200k, and _value: 1 ether) AND (_gas: 100k, _value: 0.5 ether) are sent in an option to the LayerZeroEndpoint, * that becomes (300k, 1.5 ether) when the message is executed on the remote lzReceive() function. */ function addExecutorLzReceiveOption( bytes memory _options, uint128 _gas, uint128 _value ) internal pure onlyType3(_options) returns (bytes memory) { bytes memory option = ExecutorOptions.encodeLzReceiveOption(_gas, _value); return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_LZRECEIVE, option); } /** * @dev Adds an executor native drop option to the existing options. * @param _options The existing options container. * @param _amount The amount for the native value that is airdropped to the 'receiver'. * @param _receiver The receiver address for the native drop option. * @return options The updated options container. * * @dev When multiples of this option are added, they are summed by the executor on the remote chain. */ function addExecutorNativeDropOption( bytes memory _options, uint128 _amount, bytes32 _receiver ) internal pure onlyType3(_options) returns (bytes memory) { bytes memory option = ExecutorOptions.encodeNativeDropOption(_amount, _receiver); return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_NATIVE_DROP, option); } // /** // * @dev Adds an executor native drop option to the existing options. // * @param _options The existing options container. // * @param _amount The amount for the native value that is airdropped to the 'receiver'. // * @param _receiver The receiver address for the native drop option. // * @return options The updated options container. // * // * @dev When multiples of this option are added, they are summed by the executor on the remote chain. // */ function addExecutorLzReadOption( bytes memory _options, uint128 _gas, uint32 _size, uint128 _value ) internal pure onlyType3(_options) returns (bytes memory) { bytes memory option = ExecutorOptions.encodeLzReadOption(_gas, _size, _value); return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_LZREAD, option); } /** * @dev Adds an executor LZ compose option to the existing options. * @param _options The existing options container. * @param _index The index for the lzCompose() function call. * @param _gas The gasLimit for the lzCompose() function call. * @param _value The msg.value for the lzCompose() function call. * @return options The updated options container. * * @dev When multiples of this option are added, they are summed PER index by the executor on the remote chain. * @dev If the OApp sends N lzCompose calls on the remote, you must provide N incremented indexes starting with 0. * ie. When your remote OApp composes (N = 3) messages, you must set this option for index 0,1,2 */ function addExecutorLzComposeOption( bytes memory _options, uint16 _index, uint128 _gas, uint128 _value ) internal pure onlyType3(_options) returns (bytes memory) { bytes memory option = ExecutorOptions.encodeLzComposeOption(_index, _gas, _value); return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_LZCOMPOSE, option); } /** * @dev Adds an executor ordered execution option to the existing options. * @param _options The existing options container. * @return options The updated options container. */ function addExecutorOrderedExecutionOption( bytes memory _options ) internal pure onlyType3(_options) returns (bytes memory) { return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_ORDERED_EXECUTION, bytes("")); } /** * @dev Adds a DVN pre-crime option to the existing options. * @param _options The existing options container. * @param _dvnIdx The DVN index for the pre-crime option. * @return options The updated options container. */ function addDVNPreCrimeOption( bytes memory _options, uint8 _dvnIdx ) internal pure onlyType3(_options) returns (bytes memory) { return addDVNOption(_options, _dvnIdx, DVNOptions.OPTION_TYPE_PRECRIME, bytes("")); } /** * @dev Adds an executor option to the existing options. * @param _options The existing options container. * @param _optionType The type of the executor option. * @param _option The encoded data for the executor option. * @return options The updated options container. */ function addExecutorOption( bytes memory _options, uint8 _optionType, bytes memory _option ) internal pure onlyType3(_options) returns (bytes memory) { return abi.encodePacked( _options, ExecutorOptions.WORKER_ID, _option.length.toUint16() + 1, // +1 for optionType _optionType, _option ); } /** * @dev Adds a DVN option to the existing options. * @param _options The existing options container. * @param _dvnIdx The DVN index for the DVN option. * @param _optionType The type of the DVN option. * @param _option The encoded data for the DVN option. * @return options The updated options container. */ function addDVNOption( bytes memory _options, uint8 _dvnIdx, uint8 _optionType, bytes memory _option ) internal pure onlyType3(_options) returns (bytes memory) { return abi.encodePacked( _options, DVNOptions.WORKER_ID, _option.length.toUint16() + 2, // +2 for optionType and dvnIdx _dvnIdx, _optionType, _option ); } /** * @dev Encodes legacy options of type 1. * @param _executionGas The gasLimit value passed to lzReceive(). * @return legacyOptions The encoded legacy options. */ function encodeLegacyOptionsType1(uint256 _executionGas) internal pure returns (bytes memory) { if (_executionGas > type(uint128).max) revert InvalidSize(type(uint128).max, _executionGas); return abi.encodePacked(TYPE_1, _executionGas); } /** * @dev Encodes legacy options of type 2. * @param _executionGas The gasLimit value passed to lzReceive(). * @param _nativeForDst The amount of native air dropped to the receiver. * @param _receiver The _nativeForDst receiver address. * @return legacyOptions The encoded legacy options of type 2. */ function encodeLegacyOptionsType2( uint256 _executionGas, uint256 _nativeForDst, bytes memory _receiver // @dev Use bytes instead of bytes32 in legacy type 2 for _receiver. ) internal pure returns (bytes memory) { if (_executionGas > type(uint128).max) revert InvalidSize(type(uint128).max, _executionGas); if (_nativeForDst > type(uint128).max) revert InvalidSize(type(uint128).max, _nativeForDst); if (_receiver.length > 32) revert InvalidSize(32, _receiver.length); return abi.encodePacked(TYPE_2, _executionGas, _nativeForDst, _receiver); } }
// 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: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {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); _; } /** * @dev See {IERC165-supportsInterface}. */ 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` to `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.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for storage of packed unsigned integers. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibMap.sol) library LibMap { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev A uint8 map in storage. struct Uint8Map { mapping(uint256 => uint256) map; } /// @dev A uint16 map in storage. struct Uint16Map { mapping(uint256 => uint256) map; } /// @dev A uint32 map in storage. struct Uint32Map { mapping(uint256 => uint256) map; } /// @dev A uint40 map in storage. Useful for storing timestamps up to 34841 A.D. struct Uint40Map { mapping(uint256 => uint256) map; } /// @dev A uint64 map in storage. struct Uint64Map { mapping(uint256 => uint256) map; } /// @dev A uint128 map in storage. struct Uint128Map { mapping(uint256 => uint256) map; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* GETTERS / SETTERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the uint8 value at `index` in `map`. function get(Uint8Map storage map, uint256 index) internal view returns (uint8 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(5, index)) result := byte(and(31, not(index)), sload(keccak256(0x00, 0x40))) } } /// @dev Updates the uint8 value at `index` in `map`. function set(Uint8Map storage map, uint256 index, uint8 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(5, index)) let s := keccak256(0x00, 0x40) // Storage slot. mstore(0x00, sload(s)) mstore8(and(31, not(index)), value) sstore(s, mload(0x00)) } } /// @dev Returns the uint16 value at `index` in `map`. function get(Uint16Map storage map, uint256 index) internal view returns (uint16 result) { result = uint16(map.map[index >> 4] >> ((index & 15) << 4)); } /// @dev Updates the uint16 value at `index` in `map`. function set(Uint16Map storage map, uint256 index, uint16 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(4, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(4, and(index, 15)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint32 value at `index` in `map`. function get(Uint32Map storage map, uint256 index) internal view returns (uint32 result) { result = uint32(map.map[index >> 3] >> ((index & 7) << 5)); } /// @dev Updates the uint32 value at `index` in `map`. function set(Uint32Map storage map, uint256 index, uint32 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(3, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(5, and(index, 7)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint40 value at `index` in `map`. function get(Uint40Map storage map, uint256 index) internal view returns (uint40 result) { unchecked { result = uint40(map.map[index / 6] >> ((index % 6) * 40)); } } /// @dev Updates the uint40 value at `index` in `map`. function set(Uint40Map storage map, uint256 index, uint40 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, div(index, 6)) let s := keccak256(0x00, 0x40) // Storage slot. let o := mul(40, mod(index, 6)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint64 value at `index` in `map`. function get(Uint64Map storage map, uint256 index) internal view returns (uint64 result) { result = uint64(map.map[index >> 2] >> ((index & 3) << 6)); } /// @dev Updates the uint64 value at `index` in `map`. function set(Uint64Map storage map, uint256 index, uint64 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(2, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(6, and(index, 3)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffffffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint128 value at `index` in `map`. function get(Uint128Map storage map, uint256 index) internal view returns (uint128 result) { result = uint128(map.map[index >> 1] >> ((index & 1) << 7)); } /// @dev Updates the uint128 value at `index` in `map`. function set(Uint128Map storage map, uint256 index, uint128 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(1, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(7, and(index, 1)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffffffffffffffffffffffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the value at `index` in `map`. function get(mapping(uint256 => uint256) storage map, uint256 index, uint256 bitWidth) internal view returns (uint256 result) { unchecked { uint256 d = _rawDiv(256, bitWidth); // Bucket size. uint256 m = (1 << bitWidth) - 1; // Value mask. result = (map[_rawDiv(index, d)] >> (_rawMod(index, d) * bitWidth)) & m; } } /// @dev Updates the value at `index` in `map`. function set( mapping(uint256 => uint256) storage map, uint256 index, uint256 value, uint256 bitWidth ) internal { unchecked { uint256 d = _rawDiv(256, bitWidth); // Bucket size. uint256 m = (1 << bitWidth) - 1; // Value mask. uint256 o = _rawMod(index, d) * bitWidth; // Storage slot offset (bits). map[_rawDiv(index, d)] ^= (((map[_rawDiv(index, d)] >> o) ^ value) & m) << o; } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BINARY SEARCH */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // The following functions search in the range of [`start`, `end`) // (i.e. `start <= index < end`). // The range must be sorted in ascending order. // `index` precedence: equal to > nearest before > nearest after. // An invalid search range will simply return `(found = false, index = start)`. /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint8Map storage map, uint8 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 8); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint16Map storage map, uint16 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 16); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint32Map storage map, uint32 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 32); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint40Map storage map, uint40 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 40); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint64Map storage map, uint64 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 64); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint128Map storage map, uint128 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 128); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted( mapping(uint256 => uint256) storage map, uint256 needle, uint256 start, uint256 end, uint256 bitWidth ) internal view returns (bool found, uint256 index) { unchecked { if (start >= end) end = start; uint256 t; uint256 o = start - 1; // Offset to derive the actual index. uint256 l = 1; // Low. uint256 d = _rawDiv(256, bitWidth); // Bucket size. uint256 m = (1 << bitWidth) - 1; // Value mask. uint256 h = end - start; // High. while (true) { index = (l & h) + ((l ^ h) >> 1); if (l > h) break; t = (map[_rawDiv(index + o, d)] >> (_rawMod(index + o, d) * bitWidth)) & m; if (t == needle) break; if (needle <= t) h = index - 1; else l = index + 1; } /// @solidity memory-safe-assembly assembly { m := or(iszero(index), iszero(bitWidth)) found := iszero(or(xor(t, needle), m)) index := add(o, xor(index, mul(xor(index, 1), m))) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns `x / y`, returning 0 if `y` is zero. function _rawDiv(uint256 x, uint256 y) private pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := div(x, y) } } /// @dev Returns `x % y`, returning 0 if `y` is zero. function _rawMod(uint256 x, uint256 y) private pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mod(x, y) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface IExclusiveDelegateResolver { function exclusiveOwnerByRights(address contractAddress, uint256 tokenId, bytes24 rights) external view returns (address); function generateRightsWithExpiration(bytes24 rightsIdentifier, uint40 expiration) external view returns (bytes32); }
// SPDX-License-Identifier: CC0-1.0 pragma solidity >=0.8.13; /** * @title IDelegateRegistry * @custom:version 2.0 * @custom:author foobar (0xfoobar) * @notice A standalone immutable registry storing delegated permissions from one address to another */ interface IDelegateRegistry { /// @notice Delegation type, NONE is used when a delegation does not exist or is revoked enum DelegationType { NONE, ALL, CONTRACT, ERC721, ERC20, ERC1155 } /// @notice Struct for returning delegations struct Delegation { DelegationType type_; address to; address from; bytes32 rights; address contract_; uint256 tokenId; uint256 amount; } /// @notice Emitted when an address delegates or revokes rights for their entire wallet event DelegateAll(address indexed from, address indexed to, bytes32 rights, bool enable); /// @notice Emitted when an address delegates or revokes rights for a contract address event DelegateContract( address indexed from, address indexed to, address indexed contract_, bytes32 rights, bool enable ); /// @notice Emitted when an address delegates or revokes rights for an ERC721 tokenId event DelegateERC721( address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, bool enable ); /// @notice Emitted when an address delegates or revokes rights for an amount of ERC20 tokens event DelegateERC20( address indexed from, address indexed to, address indexed contract_, bytes32 rights, uint256 amount ); /// @notice Emitted when an address delegates or revokes rights for an amount of an ERC1155 tokenId event DelegateERC1155( address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, uint256 amount ); /// @notice Thrown if multicall calldata is malformed error MulticallFailed(); /** * ----------- WRITE ----------- */ /** * @notice Call multiple functions in the current contract and return the data from all of them if they all succeed * @param data The encoded function data for each of the calls to make to this contract * @return results The results from each of the calls passed in via data */ function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); /** * @notice Allow the delegate to act on behalf of `msg.sender` for all contracts * @param to The address to act as delegate * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights * @param enable Whether to enable or disable this delegation, true delegates and false revokes * @return delegationHash The unique identifier of the delegation */ function delegateAll(address to, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash); /** * @notice Allow the delegate to act on behalf of `msg.sender` for a specific contract * @param to The address to act as delegate * @param contract_ The contract whose rights are being delegated * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights * @param enable Whether to enable or disable this delegation, true delegates and false revokes * @return delegationHash The unique identifier of the delegation */ function delegateContract(address to, address contract_, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash); /** * @notice Allow the delegate to act on behalf of `msg.sender` for a specific ERC721 token * @param to The address to act as delegate * @param contract_ The contract whose rights are being delegated * @param tokenId The token id to delegate * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights * @param enable Whether to enable or disable this delegation, true delegates and false revokes * @return delegationHash The unique identifier of the delegation */ function delegateERC721(address to, address contract_, uint256 tokenId, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash); /** * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC20 tokens * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound) * @param to The address to act as delegate * @param contract_ The address for the fungible token contract * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights * @param amount The amount to delegate, > 0 delegates and 0 revokes * @return delegationHash The unique identifier of the delegation */ function delegateERC20(address to, address contract_, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash); /** * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC1155 tokens * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound) * @param to The address to act as delegate * @param contract_ The address of the contract that holds the token * @param tokenId The token id to delegate * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights * @param amount The amount of that token id to delegate, > 0 delegates and 0 revokes * @return delegationHash The unique identifier of the delegation */ function delegateERC1155(address to, address contract_, uint256 tokenId, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash); /** * ----------- CHECKS ----------- */ /** * @notice Check if `to` is a delegate of `from` for the entire wallet * @param to The potential delegate address * @param from The potential address who delegated rights * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only * @return valid Whether delegate is granted to act on the from's behalf */ function checkDelegateForAll(address to, address from, bytes32 rights) external view returns (bool); /** * @notice Check if `to` is a delegate of `from` for the specified `contract_` or the entire wallet * @param to The delegated address to check * @param contract_ The specific contract address being checked * @param from The cold wallet who issued the delegation * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only * @return valid Whether delegate is granted to act on from's behalf for entire wallet or that specific contract */ function checkDelegateForContract(address to, address from, address contract_, bytes32 rights) external view returns (bool); /** * @notice Check if `to` is a delegate of `from` for the specific `contract` and `tokenId`, the entire `contract_`, or the entire wallet * @param to The delegated address to check * @param contract_ The specific contract address being checked * @param tokenId The token id for the token to delegating * @param from The wallet that issued the delegation * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only * @return valid Whether delegate is granted to act on from's behalf for entire wallet, that contract, or that specific tokenId */ function checkDelegateForERC721(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (bool); /** * @notice Returns the amount of ERC20 tokens the delegate is granted rights to act on the behalf of * @param to The delegated address to check * @param contract_ The address of the token contract * @param from The cold wallet who issued the delegation * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only * @return balance The delegated balance, which will be 0 if the delegation does not exist */ function checkDelegateForERC20(address to, address from, address contract_, bytes32 rights) external view returns (uint256); /** * @notice Returns the amount of a ERC1155 tokens the delegate is granted rights to act on the behalf of * @param to The delegated address to check * @param contract_ The address of the token contract * @param tokenId The token id to check the delegated amount of * @param from The cold wallet who issued the delegation * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only * @return balance The delegated balance, which will be 0 if the delegation does not exist */ function checkDelegateForERC1155(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (uint256); /** * ----------- ENUMERATIONS ----------- */ /** * @notice Returns all enabled delegations a given delegate has received * @param to The address to retrieve delegations for * @return delegations Array of Delegation structs */ function getIncomingDelegations(address to) external view returns (Delegation[] memory delegations); /** * @notice Returns all enabled delegations an address has given out * @param from The address to retrieve delegations for * @return delegations Array of Delegation structs */ function getOutgoingDelegations(address from) external view returns (Delegation[] memory delegations); /** * @notice Returns all hashes associated with enabled delegations an address has received * @param to The address to retrieve incoming delegation hashes for * @return delegationHashes Array of delegation hashes */ function getIncomingDelegationHashes(address to) external view returns (bytes32[] memory delegationHashes); /** * @notice Returns all hashes associated with enabled delegations an address has given out * @param from The address to retrieve outgoing delegation hashes for * @return delegationHashes Array of delegation hashes */ function getOutgoingDelegationHashes(address from) external view returns (bytes32[] memory delegationHashes); /** * @notice Returns the delegations for a given array of delegation hashes * @param delegationHashes is an array of hashes that correspond to delegations * @return delegations Array of Delegation structs, return empty structs for nonexistent or revoked delegations */ function getDelegationsFromHashes(bytes32[] calldata delegationHashes) external view returns (Delegation[] memory delegations); /** * ----------- STORAGE ACCESS ----------- */ /** * @notice Allows external contracts to read arbitrary storage slots */ function readSlot(bytes32 location) external view returns (bytes32); /** * @notice Allows external contracts to read an arbitrary array of storage slots */ function readSlots(bytes32[] calldata locations) external view returns (bytes32[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; interface INFTShadow is IERC721 { function read(uint256[] calldata tokenIds, uint32[] calldata eids) external payable returns (bytes32); function readWithCallback(uint256[] calldata tokenIds, uint32[] calldata eids, uint128 callbackGasLimit) external payable returns (bytes32); function burn(uint256 tokenId) external; function send( uint32 eid, uint256[] calldata tokenIds, address beneficiary, address refundRecipient, uint128 supplementalGasLimit ) external payable; function executeCallback(bytes32 guid) external; function locked(uint256 tokenId) external view returns (bool); function shadowModeEnabled() external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IOAppMapper { function lzMap(bytes calldata _request, bytes calldata _response) external view returns (bytes memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IOAppReducer { function lzReduce(bytes calldata _cmd, bytes[] calldata _responses) external view returns (bytes memory); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.28; library SafeCall { /// @notice calls a contract with a specified gas limit and value and captures the return data /// @dev copied from https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol. /// @param _target The address to call /// @param _gas The amount of gas to forward to the remote contract /// @param _value The value in wei to send to the remote contract /// @param _maxCopy The maximum number of bytes of returndata to copy /// to memory. /// @param _calldata The data to send to the remote contract /// @return success and returndata, as `.call()`. Returndata is capped to /// `_maxCopy` bytes. function safeCall(address _target, uint256 _gas, uint256 _value, uint16 _maxCopy, bytes memory _calldata) internal returns (bool, bytes memory) { // set up for assembly call uint256 _toCopy; bool _success; bytes memory _returnData = new bytes(_maxCopy); // dispatch message to recipient // by assembly calling "handle" function // we call via assembly to avoid memcopying a very large returndata // returned by a malicious contract assembly { _success := call( _gas, // gas _target, // recipient _value, // ether value add(_calldata, 0x20), // inloc mload(_calldata), // inlen 0, // outloc 0 // outlen ) // limit our copy to 256 bytes _toCopy := returndatasize() if gt(_toCopy, _maxCopy) { _toCopy := _maxCopy } // Store the length of the copied bytes mstore(_returnData, _toCopy) // copy the bytes from returndata[0:_toCopy] returndatacopy(add(_returnData, 0x20), 0, _toCopy) } return (_success, _returnData); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; struct CollectionConfig { uint32 baseCollectionChainId; uint32 baseCollectionEid; uint32 baseCollectionPerNftOwnershipUpdateCost; // cost of transferring an NFT from the base collection. If 0, default of 100_000 is used address shadowAddress; // Local shadow address for this chain }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; interface ILayerZeroEndpointLocator { function endpoint() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @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 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 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 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 IMessagingContext { function isSendingMessage() external view returns (bool); function getSendContext() external view returns (uint32 dstEid, address sender); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; // @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers // solhint-disable-next-line no-unused-import import { OAppSender, MessagingFee, MessagingReceipt } from "./OAppSender.sol"; // @dev Import the 'Origin' so it's exposed to OApp implementers // solhint-disable-next-line no-unused-import import { OAppReceiver, Origin } from "./OAppReceiver.sol"; import { OAppCore } from "./OAppCore.sol"; /** * @title OApp * @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality. */ abstract contract OApp is OAppSender, OAppReceiver { /** * @dev Constructor to initialize the OApp with the provided endpoint and owner. * @param _endpoint The address of the LOCAL LayerZero endpoint. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. */ constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {} /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol implementation. * @return receiverVersion The version of the OAppReceiver.sol implementation. */ function oAppVersion() public pure virtual override(OAppSender, OAppReceiver) returns (uint64 senderVersion, uint64 receiverVersion) { return (SENDER_VERSION, RECEIVER_VERSION); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @dev Struct representing enforced option parameters. */ struct EnforcedOptionParam { uint32 eid; // Endpoint ID uint16 msgType; // Message Type bytes options; // Additional options } /** * @title IOAppOptionsType3 * @dev Interface for the OApp with Type 3 Options, allowing the setting and combining of enforced options. */ interface IOAppOptionsType3 { // Custom error message for invalid options error InvalidOptions(bytes options); // Event emitted when enforced options are set event EnforcedOptionSet(EnforcedOptionParam[] _enforcedOptions); /** * @notice Sets enforced options for specific endpoint and message type combinations. * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options. */ function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) external; /** * @notice Combines options for a given endpoint and message type. * @param _eid The endpoint ID. * @param _msgType The OApp message type. * @param _extraOptions Additional options passed by the caller. * @return options The combination of caller specified options AND enforced options. */ function combineOptions( uint32 _eid, uint16 _msgType, bytes calldata _extraOptions ) external view returns (bytes memory options); }
// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equal_nonAligned(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let endMinusWord := add(_preBytes, length) let mc := add(_preBytes, 0x20) let cc := add(_postBytes, 0x20) for { // the next line is the loop condition: // while(uint256(mc < endWord) + cb == 2) } eq(add(lt(mc, endMinusWord), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } // Only if still successful // For <1 word tail bytes if gt(success, 0) { // Get the remainder of length/32 // length % 32 = AND(length, 32 - 1) let numTailBytes := and(length, 0x1f) let mcRem := mload(mc) let ccRem := mload(cc) for { let i := 0 // the next line is the loop condition: // while(uint256(i < numTailBytes) + cb == 2) } eq(add(lt(i, numTailBytes), cb), 2) { i := add(i, 1) } { if iszero(eq(byte(i, mcRem), byte(i, ccRem))) { // unsuccess: success := 0 cb := 0 } } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; import "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/CalldataBytesLib.sol"; library ExecutorOptions { using CalldataBytesLib for bytes; uint8 internal constant WORKER_ID = 1; uint8 internal constant OPTION_TYPE_LZRECEIVE = 1; uint8 internal constant OPTION_TYPE_NATIVE_DROP = 2; uint8 internal constant OPTION_TYPE_LZCOMPOSE = 3; uint8 internal constant OPTION_TYPE_ORDERED_EXECUTION = 4; uint8 internal constant OPTION_TYPE_LZREAD = 5; error Executor_InvalidLzReceiveOption(); error Executor_InvalidNativeDropOption(); error Executor_InvalidLzComposeOption(); error Executor_InvalidLzReadOption(); /// @dev decode the next executor option from the options starting from the specified cursor /// @param _options [executor_id][executor_option][executor_id][executor_option]... /// executor_option = [option_size][option_type][option] /// option_size = len(option_type) + len(option) /// executor_id: uint8, option_size: uint16, option_type: uint8, option: bytes /// @param _cursor the cursor to start decoding from /// @return optionType the type of the option /// @return option the option of the executor /// @return cursor the cursor to start decoding the next executor option function nextExecutorOption( bytes calldata _options, uint256 _cursor ) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) { unchecked { // skip worker id cursor = _cursor + 1; // read option size uint16 size = _options.toU16(cursor); cursor += 2; // read option type optionType = _options.toU8(cursor); // startCursor and endCursor are used to slice the option from _options uint256 startCursor = cursor + 1; // skip option type uint256 endCursor = cursor + size; option = _options[startCursor:endCursor]; cursor += size; } } function decodeLzReceiveOption(bytes calldata _option) internal pure returns (uint128 gas, uint128 value) { if (_option.length != 16 && _option.length != 32) revert Executor_InvalidLzReceiveOption(); gas = _option.toU128(0); value = _option.length == 32 ? _option.toU128(16) : 0; } function decodeNativeDropOption(bytes calldata _option) internal pure returns (uint128 amount, bytes32 receiver) { if (_option.length != 48) revert Executor_InvalidNativeDropOption(); amount = _option.toU128(0); receiver = _option.toB32(16); } function decodeLzComposeOption( bytes calldata _option ) internal pure returns (uint16 index, uint128 gas, uint128 value) { if (_option.length != 18 && _option.length != 34) revert Executor_InvalidLzComposeOption(); index = _option.toU16(0); gas = _option.toU128(2); value = _option.length == 34 ? _option.toU128(18) : 0; } function decodeLzReadOption( bytes calldata _option ) internal pure returns (uint128 gas, uint32 calldataSize, uint128 value) { if (_option.length != 20 && _option.length != 36) revert Executor_InvalidLzReadOption(); gas = _option.toU128(0); calldataSize = _option.toU32(16); value = _option.length == 36 ? _option.toU128(20) : 0; } function encodeLzReceiveOption(uint128 _gas, uint128 _value) internal pure returns (bytes memory) { return _value == 0 ? abi.encodePacked(_gas) : abi.encodePacked(_gas, _value); } function encodeNativeDropOption(uint128 _amount, bytes32 _receiver) internal pure returns (bytes memory) { return abi.encodePacked(_amount, _receiver); } function encodeLzComposeOption(uint16 _index, uint128 _gas, uint128 _value) internal pure returns (bytes memory) { return _value == 0 ? abi.encodePacked(_index, _gas) : abi.encodePacked(_index, _gas, _value); } function encodeLzReadOption( uint128 _gas, uint32 _calldataSize, uint128 _value ) internal pure returns (bytes memory) { return _value == 0 ? abi.encodePacked(_gas, _calldataSize) : abi.encodePacked(_gas, _calldataSize, _value); } }
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; import { BytesLib } from "solidity-bytes-utils/contracts/BytesLib.sol"; import { BitMap256 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/BitMaps.sol"; import { CalldataBytesLib } from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/CalldataBytesLib.sol"; library DVNOptions { using CalldataBytesLib for bytes; using BytesLib for bytes; uint8 internal constant WORKER_ID = 2; uint8 internal constant OPTION_TYPE_PRECRIME = 1; error DVN_InvalidDVNIdx(); error DVN_InvalidDVNOptions(uint256 cursor); /// @dev group dvn options by its idx /// @param _options [dvn_id][dvn_option][dvn_id][dvn_option]... /// dvn_option = [option_size][dvn_idx][option_type][option] /// option_size = len(dvn_idx) + len(option_type) + len(option) /// dvn_id: uint8, dvn_idx: uint8, option_size: uint16, option_type: uint8, option: bytes /// @return dvnOptions the grouped options, still share the same format of _options /// @return dvnIndices the dvn indices function groupDVNOptionsByIdx( bytes memory _options ) internal pure returns (bytes[] memory dvnOptions, uint8[] memory dvnIndices) { if (_options.length == 0) return (dvnOptions, dvnIndices); uint8 numDVNs = getNumDVNs(_options); // if there is only 1 dvn, we can just return the whole options if (numDVNs == 1) { dvnOptions = new bytes[](1); dvnOptions[0] = _options; dvnIndices = new uint8[](1); dvnIndices[0] = _options.toUint8(3); // dvn idx return (dvnOptions, dvnIndices); } // otherwise, we need to group the options by dvn_idx dvnIndices = new uint8[](numDVNs); dvnOptions = new bytes[](numDVNs); unchecked { uint256 cursor = 0; uint256 start = 0; uint8 lastDVNIdx = 255; // 255 is an invalid dvn_idx while (cursor < _options.length) { ++cursor; // skip worker_id // optionLength asserted in getNumDVNs (skip check) uint16 optionLength = _options.toUint16(cursor); cursor += 2; // dvnIdx asserted in getNumDVNs (skip check) uint8 dvnIdx = _options.toUint8(cursor); // dvnIdx must equal to the lastDVNIdx for the first option // so it is always skipped in the first option // this operation slices out options whenever the scan finds a different lastDVNIdx if (lastDVNIdx == 255) { lastDVNIdx = dvnIdx; } else if (dvnIdx != lastDVNIdx) { uint256 len = cursor - start - 3; // 3 is for worker_id and option_length bytes memory opt = _options.slice(start, len); _insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, opt); // reset the start and lastDVNIdx start += len; lastDVNIdx = dvnIdx; } cursor += optionLength; } // skip check the cursor here because the cursor is asserted in getNumDVNs // if we have reached the end of the options, we need to process the last dvn uint256 size = cursor - start; bytes memory op = _options.slice(start, size); _insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, op); // revert dvnIndices to start from 0 for (uint8 i = 0; i < numDVNs; ++i) { --dvnIndices[i]; } } } function _insertDVNOptions( bytes[] memory _dvnOptions, uint8[] memory _dvnIndices, uint8 _dvnIdx, bytes memory _newOptions ) internal pure { // dvnIdx starts from 0 but default value of dvnIndices is 0, // so we tell if the slot is empty by adding 1 to dvnIdx if (_dvnIdx == 255) revert DVN_InvalidDVNIdx(); uint8 dvnIdxAdj = _dvnIdx + 1; for (uint256 j = 0; j < _dvnIndices.length; ++j) { uint8 index = _dvnIndices[j]; if (dvnIdxAdj == index) { _dvnOptions[j] = abi.encodePacked(_dvnOptions[j], _newOptions); break; } else if (index == 0) { // empty slot, that means it is the first time we see this dvn _dvnIndices[j] = dvnIdxAdj; _dvnOptions[j] = _newOptions; break; } } } /// @dev get the number of unique dvns /// @param _options the format is the same as groupDVNOptionsByIdx function getNumDVNs(bytes memory _options) internal pure returns (uint8 numDVNs) { uint256 cursor = 0; BitMap256 bitmap; // find number of unique dvn_idx unchecked { while (cursor < _options.length) { ++cursor; // skip worker_id uint16 optionLength = _options.toUint16(cursor); cursor += 2; if (optionLength < 2) revert DVN_InvalidDVNOptions(cursor); // at least 1 byte for dvn_idx and 1 byte for option_type uint8 dvnIdx = _options.toUint8(cursor); // if dvnIdx is not set, increment numDVNs // max num of dvns is 255, 255 is an invalid dvn_idx // The order of the dvnIdx is not required to be sequential, as enforcing the order may weaken // the composability of the options. e.g. if we refrain from enforcing the order, an OApp that has // already enforced certain options can append additional options to the end of the enforced // ones without restrictions. if (dvnIdx == 255) revert DVN_InvalidDVNIdx(); if (!bitmap.get(dvnIdx)) { ++numDVNs; bitmap = bitmap.set(dvnIdx); } cursor += optionLength; } } if (cursor != _options.length) revert DVN_InvalidDVNOptions(cursor); } /// @dev decode the next dvn option from _options starting from the specified cursor /// @param _options the format is the same as groupDVNOptionsByIdx /// @param _cursor the cursor to start decoding /// @return optionType the type of the option /// @return option the option /// @return cursor the cursor to start decoding the next option function nextDVNOption( bytes calldata _options, uint256 _cursor ) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) { unchecked { // skip worker id cursor = _cursor + 1; // read option size uint16 size = _options.toU16(cursor); cursor += 2; // read option type optionType = _options.toU8(cursor + 1); // skip dvn_idx // startCursor and endCursor are used to slice the option from _options uint256 startCursor = cursor + 2; // skip option type and dvn_idx uint256 endCursor = cursor + size; option = _options[startCursor:endCursor]; cursor += size; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @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 signaling 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.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.1.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 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; import { OAppCore } from "./OAppCore.sol"; /** * @title OAppSender * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint. */ abstract contract OAppSender is OAppCore { using SafeERC20 for IERC20; // Custom error messages error NotEnoughNative(uint256 msgValue); error LzTokenUnavailable(); // @dev The version of the OAppSender implementation. // @dev Version is bumped when changes are made to this contract. uint64 internal constant SENDER_VERSION = 1; /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. * * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented. * ie. this is a SEND only OApp. * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions */ function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) { return (SENDER_VERSION, 0); } /** * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens. * @return fee The calculated MessagingFee for the message. * - nativeFee: The native fee for the message. * - lzTokenFee: The LZ token fee for the message. */ function _quote( uint32 _dstEid, bytes memory _message, bytes memory _options, bool _payInLzToken ) internal view virtual returns (MessagingFee memory fee) { return endpoint.quote( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken), address(this) ); } /** * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _fee The calculated LayerZero fee for the message. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess fee values sent to the endpoint. * @return receipt The receipt for the sent message. * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function _lzSend( uint32 _dstEid, bytes memory _message, bytes memory _options, MessagingFee memory _fee, address _refundAddress ) internal virtual returns (MessagingReceipt memory receipt) { // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint. uint256 messageValue = _payNative(_fee.nativeFee); if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee); return // solhint-disable-next-line check-send-result endpoint.send{ value: messageValue }( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0), _refundAddress ); } /** * @dev Internal function to pay the native fee associated with the message. * @param _nativeFee The native fee to be paid. * @return nativeFee The amount of native currency paid. * * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction, * this will need to be overridden because msg.value would contain multiple lzFees. * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency. * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees. * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time. */ function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) { if (msg.value != _nativeFee) revert NotEnoughNative(msg.value); return _nativeFee; } /** * @dev Internal function to pay the LZ token fee associated with the message. * @param _lzTokenFee The LZ token fee to be paid. * * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint. * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend(). */ function _payLzToken(uint256 _lzTokenFee) internal virtual { // @dev Cannot cache the token because it is not immutable in the endpoint. address lzToken = endpoint.lzToken(); if (lzToken == address(0)) revert LzTokenUnavailable(); // Pay LZ token fee by sending tokens to the endpoint. IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IOAppReceiver, Origin } from "./interfaces/IOAppReceiver.sol"; import { OAppCore } from "./OAppCore.sol"; /** * @title OAppReceiver * @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers. */ abstract contract OAppReceiver is IOAppReceiver, OAppCore { // Custom error message for when the caller is not the registered endpoint/ error OnlyEndpoint(address addr); // @dev The version of the OAppReceiver implementation. // @dev Version is bumped when changes are made to this contract. uint64 internal constant RECEIVER_VERSION = 2; /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. * * @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented. * ie. this is a RECEIVE only OApp. * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions. */ function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) { return (0, RECEIVER_VERSION); } /** * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint. * @dev _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @dev _message The lzReceive payload. * @param _sender The sender address. * @return isSender Is a valid sender. * * @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer. * @dev The default sender IS the OAppReceiver implementer. */ function isComposeMsgSender( Origin calldata /*_origin*/, bytes calldata /*_message*/, address _sender ) public view virtual returns (bool) { return _sender == address(this); } /** * @notice Checks if the path initialization is allowed based on the provided origin. * @param origin The origin information containing the source endpoint and sender address. * @return Whether the path has been initialized. * * @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received. * @dev This defaults to assuming if a peer has been set, its initialized. * Can be overridden by the OApp if there is other logic to determine this. */ function allowInitializePath(Origin calldata origin) public view virtual returns (bool) { return peers[origin.srcEid] == origin.sender; } /** * @notice Retrieves the next nonce for a given source endpoint and sender address. * @dev _srcEid The source endpoint ID. * @dev _sender The sender address. * @return nonce The next nonce. * * @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement. * @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered. * @dev This is also enforced by the OApp. * @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0. */ function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) { return 0; } /** * @dev Entry point for receiving messages or packets from the endpoint. * @param _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @param _guid The unique identifier for the received LayerZero message. * @param _message The payload of the received message. * @param _executor The address of the executor for the received message. * @param _extraData Additional arbitrary data provided by the corresponding executor. * * @dev Entry point for receiving msg/packet from the LayerZero endpoint. */ function lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) public payable virtual { // Ensures that only the endpoint can attempt to lzReceive() messages to this OApp. if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender); // Ensure that the sender matches the expected peer for the source endpoint. if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender); // Call the internal OApp implementation of lzReceive. _lzReceive(_origin, _guid, _message, _executor, _extraData); } /** * @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation. */ function _lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal virtual; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IOAppCore, ILayerZeroEndpointV2 } from "./interfaces/IOAppCore.sol"; /** * @title OAppCore * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations. */ abstract contract OAppCore is IOAppCore, Ownable { // The LayerZero endpoint associated with the given OApp ILayerZeroEndpointV2 public immutable endpoint; // Mapping to store peers associated with corresponding endpoints mapping(uint32 eid => bytes32 peer) public peers; /** * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate. * @param _endpoint The address of the LOCAL Layer Zero endpoint. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * * @dev The delegate typically should be set as the owner of the contract. */ constructor(address _endpoint, address _delegate) { endpoint = ILayerZeroEndpointV2(_endpoint); if (_delegate == address(0)) revert InvalidDelegate(); endpoint.setDelegate(_delegate); } /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. * * @dev Only the owner/admin of the OApp can call this function. * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp. * @dev Set this to bytes32(0) to remove the peer address. * @dev Peer is a bytes32 to accommodate non-evm chains. */ function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner { _setPeer(_eid, _peer); } /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. * * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp. * @dev Set this to bytes32(0) to remove the peer address. * @dev Peer is a bytes32 to accommodate non-evm chains. */ function _setPeer(uint32 _eid, bytes32 _peer) internal virtual { peers[_eid] = _peer; emit PeerSet(_eid, _peer); } /** * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set. * ie. the peer is set to bytes32(0). * @param _eid The endpoint ID. * @return peer The address of the peer associated with the specified endpoint. */ function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) { bytes32 peer = peers[_eid]; if (peer == bytes32(0)) revert NoPeer(_eid); return peer; } /** * @notice Sets the delegate address for the OApp. * @param _delegate The address of the delegate to be set. * * @dev Only the owner/admin of the OApp can call this function. * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract. */ function setDelegate(address _delegate) public onlyOwner { endpoint.setDelegate(_delegate); } }
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; library CalldataBytesLib { function toU8(bytes calldata _bytes, uint256 _start) internal pure returns (uint8) { return uint8(_bytes[_start]); } function toU16(bytes calldata _bytes, uint256 _start) internal pure returns (uint16) { unchecked { uint256 end = _start + 2; return uint16(bytes2(_bytes[_start:end])); } } function toU32(bytes calldata _bytes, uint256 _start) internal pure returns (uint32) { unchecked { uint256 end = _start + 4; return uint32(bytes4(_bytes[_start:end])); } } function toU64(bytes calldata _bytes, uint256 _start) internal pure returns (uint64) { unchecked { uint256 end = _start + 8; return uint64(bytes8(_bytes[_start:end])); } } function toU128(bytes calldata _bytes, uint256 _start) internal pure returns (uint128) { unchecked { uint256 end = _start + 16; return uint128(bytes16(_bytes[_start:end])); } } function toU256(bytes calldata _bytes, uint256 _start) internal pure returns (uint256) { unchecked { uint256 end = _start + 32; return uint256(bytes32(_bytes[_start:end])); } } function toAddr(bytes calldata _bytes, uint256 _start) internal pure returns (address) { unchecked { uint256 end = _start + 20; return address(bytes20(_bytes[_start:end])); } } function toB32(bytes calldata _bytes, uint256 _start) internal pure returns (bytes32) { unchecked { uint256 end = _start + 32; return bytes32(_bytes[_start:end]); } } }
// SPDX-License-Identifier: MIT // modified from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/structs/BitMaps.sol pragma solidity ^0.8.20; type BitMap256 is uint256; using BitMaps for BitMap256 global; library BitMaps { /** * @dev Returns whether the bit at `index` is set. */ function get(BitMap256 bitmap, uint8 index) internal pure returns (bool) { uint256 mask = 1 << index; return BitMap256.unwrap(bitmap) & mask != 0; } /** * @dev Sets the bit at `index`. */ function set(BitMap256 bitmap, uint8 index) internal pure returns (BitMap256) { uint256 mask = 1 << index; return BitMap256.wrap(BitMap256.unwrap(bitmap) | mask); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; import {Address} from "../../../utils/Address.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 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 pragma solidity ^0.8.20; import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol"; interface IOAppReceiver is ILayerZeroReceiver { /** * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint. * @param _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @param _message The lzReceive payload. * @param _sender The sender address. * @return isSender Is a valid sender. * * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer. * @dev The default sender IS the OAppReceiver implementer. */ function isComposeMsgSender( Origin calldata _origin, bytes calldata _message, address _sender ) external view returns (bool isSender); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; /** * @title IOAppCore */ interface IOAppCore { // Custom error messages error OnlyPeer(uint32 eid, bytes32 sender); error NoPeer(uint32 eid); error InvalidEndpointCall(); error InvalidDelegate(); // Event emitted when a peer (OApp) is set for a corresponding endpoint event PeerSet(uint32 eid, bytes32 peer); /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. */ function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion); /** * @notice Retrieves the LayerZero endpoint associated with the OApp. * @return iEndpoint The LayerZero endpoint as an interface. */ function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint); /** * @notice Retrieves the peer (OApp) associated with a corresponding endpoint. * @param _eid The endpoint ID. * @return peer The peer address (OApp instance) associated with the corresponding endpoint. */ function peers(uint32 _eid) external view returns (bytes32 peer); /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. */ function setPeer(uint32 _eid, bytes32 _peer) external; /** * @notice Sets the delegate address for the OApp Core. * @param _delegate The address of the delegate to be set. */ function setDelegate(address _delegate) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @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.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; 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.1.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { Origin } from "./ILayerZeroEndpointV2.sol"; interface ILayerZeroReceiver { function allowInitializePath(Origin calldata _origin) external view returns (bool); function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64); function lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) external payable; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
{ "remappings": [ "solady/=lib/solady/src/", "@layerzerolabs/=node_modules/@layerzerolabs/", "@openzeppelin/=node_modules/@openzeppelin/", "solidity-bytes-utils/=node_modules/solidity-bytes-utils/", "forge-std/=lib/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "cancun", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_endpointLocator","type":"address"},{"internalType":"address","name":"_delegate","type":"address"},{"internalType":"uint32","name":"_readChannel","type":"uint32"},{"internalType":"address","name":"_delegatexyz","type":"address"},{"internalType":"address","name":"_exclusiveDelegateResolver","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":"BeneficiaryZeroAddress","type":"error"},{"inputs":[],"name":"BurnFailed","type":"error"},{"inputs":[],"name":"CollectionAlreadyRegistered","type":"error"},{"inputs":[],"name":"CollectionNotInShadowMode","type":"error"},{"inputs":[],"name":"ContractNotConfigured","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidChain","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEid","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[{"internalType":"uint16","name":"optionType","type":"uint16"}],"name":"InvalidOptionType","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"InvalidOwner","type":"error"},{"inputs":[],"name":"InvalidPayloadHash","type":"error"},{"inputs":[],"name":"InvalidReadChannel","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[],"name":"MaxLzReceiveGasAllocationExceeded","type":"error"},{"inputs":[],"name":"MintFailed","type":"error"},{"inputs":[],"name":"MismatchedCollectionAddress","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[],"name":"OnlyInternalCalls","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"PunkAdapterAlreadySet","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"StaleReadRequest","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UnauthorizedExecutor","type":"error"},{"inputs":[],"name":"UnlockFailed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroLengthArray","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"executor","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"AllowedExecutorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":true,"internalType":"bytes32","name":"sender","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"}],"name":"CachedMessageExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collectionAddress","type":"address"},{"indexed":true,"internalType":"address","name":"baseCollectionAddress","type":"address"},{"indexed":true,"internalType":"uint32","name":"baseCollectionEid","type":"uint32"}],"name":"CollectionRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enforceExecutors","type":"bool"}],"name":"EnforceExecutionSet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"indexed":false,"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"EnforcedOptionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":true,"internalType":"bytes32","name":"sender","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"reason","type":"bytes"}],"name":"MessageCached","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"punkAdapter","type":"address"}],"name":"PunkAdapterSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"readChannel","type":"uint32"}],"name":"ReadChannelSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"baseCollectionAddress","type":"address"},{"indexed":true,"internalType":"address","name":"shadowCollectionAddress","type":"address"},{"indexed":false,"internalType":"uint32[]","name":"eids","type":"uint32[]"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"ReadTriggered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"uint16","name":"confirmations","type":"uint16"}],"name":"RequiredConfirmationsSet","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":true,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":true,"internalType":"address","name":"baseCollectionAddress","type":"address"},{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"address","name":"beneficiary","type":"address"}],"name":"Sent","type":"event"},{"inputs":[],"name":"COLLECTION_REGISTRAR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CRYPTOPUNKS721_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELEGATE_REGISTRY_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXCLUSIVE_DELEGATE_RESOLVER_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHADOW_TOKEN_RIGHTS","outputs":[{"internalType":"bytes24","name":"","type":"bytes24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"THIS_CONTRACT_EID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"executor","type":"address"}],"name":"allowedExecutors","outputs":[{"internalType":"bool","name":"allowed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseCollectionAddress","type":"address"}],"name":"baseToShadow","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseCollectionAddress","type":"address"}],"name":"collectionConfigs","outputs":[{"internalType":"uint32","name":"baseCollectionChainId","type":"uint32"},{"internalType":"uint32","name":"baseCollectionEid","type":"uint32"},{"internalType":"uint32","name":"baseCollectionPerNftOwnershipUpdateCost","type":"uint32"},{"internalType":"address","name":"shadowAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"uint16","name":"_msgType","type":"uint16"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"}],"name":"combineOptions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"delegatedOwners","outputs":[{"internalType":"address","name":"delegatedOwner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enforceExecutors","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"}],"name":"enforcedOptions","outputs":[{"internalType":"bytes","name":"enforcedOption","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"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"}],"name":"executeMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"baseCollectionAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint128","name":"supplementalGasLimit","type":"uint128"}],"name":"getReadOptions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"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":"dstEid","type":"uint32"},{"internalType":"address","name":"baseCollectionAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint128","name":"supplementalGasLimit","type":"uint128"}],"name":"getSendOptions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"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":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"guid","type":"bytes32"}],"name":"initTimestamps","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"isComposeMsgSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_request","type":"bytes"},{"internalType":"bytes","name":"_response","type":"bytes"}],"name":"lzMap","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_request","type":"bytes"},{"internalType":"bytes[]","name":"_responses","type":"bytes[]"}],"name":"lzReduce","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"payloadHashes","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"punkAdapter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseCollectionAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint32[]","name":"dstEids","type":"uint32[]"},{"internalType":"uint128","name":"supplementalGasLimit","type":"uint128"}],"name":"quoteRead","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"baseCollectionAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint128","name":"supplementalGasLimit","type":"uint128"}],"name":"quoteSend","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseCollectionAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint32[]","name":"eids","type":"uint32[]"},{"internalType":"address","name":"refundRecipient","type":"address"},{"internalType":"uint128","name":"supplementalGasLimit","type":"uint128"}],"name":"read","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"readChannel","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"shadowCollectionAddress","type":"address"},{"internalType":"uint32","name":"baseCollectionChainId","type":"uint32"},{"internalType":"address","name":"baseCollectionAddress","type":"address"},{"internalType":"uint32","name":"baseCollectionEid","type":"uint32"},{"internalType":"uint32","name":"baseCollectionPerNftOwnershipUpdateCost","type":"uint32"}],"name":"registerCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_punkAdapter","type":"address"}],"name":"registerPunkAdapter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"requiredConfirmations","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"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"}],"name":"retryFailedMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"baseCollectionAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"address","name":"refundRecipient","type":"address"},{"internalType":"uint128","name":"supplementalGasLimit","type":"uint128"}],"name":"send","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"executor","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setAllowedExecutor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"baseCollectionAddress","type":"address"},{"internalType":"uint32","name":"cost","type":"uint32"}],"name":"setBaseCollectionPerNftOwnershipUpdateCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enforceExecutors","type":"bool"}],"name":"setEnforceExecutors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"setEnforcedOptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_readChannel","type":"uint32"}],"name":"setReadChannel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_channelId","type":"uint32"},{"internalType":"bool","name":"_active","type":"bool"}],"name":"setReadChannel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"confirmations","type":"uint16"}],"name":"setRequiredConfirmations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"shadowCollectionAddress","type":"address"}],"name":"shadowToBase","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"baseCollectionAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"unlockedExclusiveOwnerByRights","outputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"bool","name":"_isLocked","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101208060405234610397575f9060a081615640803803809161002282856103f9565b8339810103126103975761003581610430565b9061004260208201610430565b9061004f60408201610444565b92610068608061006160608501610430565b9301610430565b604051635e280f1160e01b81526001600160a01b0390921693909190602082600481885afa91821561038c575f926103bd575b5032156103aa575f8054326001600160a01b0319821681178355604051949290916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a36001600160a01b039081166080819052911690811561039b57803b15610397576024835f8193819563ca5eb5e160e01b845260048401525af1801561038c57610377575b5063fffff9be63ffffffff85161115610368579160209160049360e052610100526040518281014681528382526101666040836103f9565b905190206001600160401b03191660a052604051635e280f1160e01b815292839182905afa90811561031e578391610329575b5060405163416ecebf60e01b815290602090829060049082906001600160a01b03165afa90811561031e5783916102cb575b60c08290526004805463ffffffff60a01b191660a085901b63ffffffff60a01b161790555f5160206156205f395f51905f5260408561020932610455565b50610213326104ed565b5063ffffffff60045460a01c1690818152600160205282309120558151908152306020820152a1604051615061908161055f823960805181818161077701528181610d9601528181611b52015281816136e4015281816140c801526146bf015260a0518181816110e90152612af8015260c05181818161065d015281816118e301528181611de001528181611f7a01526133f0015260e0518181816109930152612b2d015261010051818181610ef20152614d170152f35b90506020813d602011610316575b816102e6602093836103f9565b8101031261031257916040916103095f5160206156205f395f51905f5294610444565b919350916101cb565b8280fd5b3d91506102d9565b6040513d85823e3d90fd5b90506020813d602011610360575b81610344602093836103f9565b81010312610312576020610359600492610430565b9150610199565b3d9150610337565b633df6e48d60e21b8552600485fd5b6103849195505f906103f9565b5f935f61012e565b6040513d5f823e3d90fd5b5f80fd5b632d618d8160e21b5f5260045ffd5b631e4fbdf760e01b5f525f60045260245ffd5b9091506020813d6020116103f1575b816103d9602093836103f9565b81010312610397576103ea90610430565b905f61009b565b3d91506103cc565b601f909101601f19168101906001600160401b0382119082101761041c57604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361039757565b519063ffffffff8216820361039757565b6001600160a01b0381165f9081525f5160206155e05f395f51905f52602052604090205460ff166104e8576001600160a01b03165f8181525f5160206155e05f395f51905f5260205260408120805460ff191660011790553391907f8970ff45bc1804c7a79662cce9df9b0403588be8e486c6f5a410a2814caa892c905f5160206155c05f395f51905f529080a4600190565b505f90565b6001600160a01b0381165f9081525f5160206156005f395f51905f52602052604090205460ff166104e8576001600160a01b03165f8181525f5160206156005f395f51905f5260205260408120805460ff191660011790553391905f5160206155c05f395f51905f528180a460019056fe60806040526004361015610011575f80fd5b5f3560e01c806301a0de05146103b457806301ffc9a7146103af57806304bd49a5146103aa578063066d5910146103a5578063108dcbdd146103a057806313137d651461039b57806317442b70146103965780631d56672114610391578063248a9ca31461038c5780632d69fc48146103875780632f2ff15d146103825780633400288b1461037d57806336568abe1461037857806336b1dd211461037357806337cb67361461036e5780634202fce11461036957806345248a3714610364578063461572f91461035f57806347c1b3171461035a5780635535d461146103555780635e280f111461035057806360eddbe41461034b5780636a4d8672146103465780636eaa6904146103415780636fe87dba1461033c578063715018a6146103375780637d25a05e1461033257806382413eac1461032d578063864c651514610328578063881ae9f8146103235780638da5cb5b1461031e57806391d14854146103195780639931516014610314578063a0238f3e1461030f578063a217fddf1461030a578063a34ac81b14610305578063ade7142d14610300578063b33b522d146102fb578063b98bd070146102f6578063bb0b6a53146102f1578063bc70b354146102ec578063bda69a0a146102e7578063c9df8167146102e2578063ca5eb5e1146102dd578063cfac96ce146102d8578063d1e1d0cc146102d3578063d547741f146102ce578063da383b97146102c9578063e052778a146102c4578063e60c287c146102bf578063eba1cf08146102ba578063f0a9e481146102b5578063f1748835146102b0578063f1c418ee146102ab578063f2fde38b146102a6578063fccc4331146102a1578063fe084c8f1461029c5763ff7bd03d14610297575f80fd5b612426565b612222565b6121fa565b612171565b61214f565b61210c565b6120c5565b612066565b612007565b611fcd565b611d2d565b611cec565b611c53565b611bc7565b611b2a565b61185b565b611815565b6117c1565b611788565b611683565b611616565b611581565b611519565b6114ff565b6114a9565b611335565b6112e3565b6112bc565b61125a565b6111e8565b61118a565b611164565b61110d565b6110c9565b610f32565b610edd565b610dc5565b610d81565b610d2b565b610b48565b610b22565b610ab3565b610a82565b6109c2565b61097e565b610936565b610905565b6108b1565b61088a565b610857565b61082d565b61080c565b61070e565b610681565b610641565b6104e4565b61041c565b6103ce565b6001600160a01b038116036103ca57565b5f80fd5b346103ca5760403660031901126103ca576004356103eb816103b9565b6001600160a01b039081165f9081526007602090815260408083206024358452825291829020549151919092168152f35b346103ca5760203660031901126103ca5760043563ffffffff60e01b81168091036103ca57602090637965db0b60e01b8114908115610461575b506040519015158152f35b6301ffc9a760e01b1490505f610456565b9181601f840112156103ca578235916001600160401b0383116103ca576020808501948460051b0101116103ca57565b606435906001600160801b03821682036103ca57565b60a435906001600160801b03821682036103ca57565b608435906001600160801b03821682036103ca57565b346103ca5760803660031901126103ca57600435610501816103b9565b6024356001600160401b0381116103ca57610520903690600401610472565b91906044356001600160401b0381116103ca57610541903690600401610472565b9361054a6104a2565b6001600160a01b0385165f90815260056020526040902061056d905b5460601c90565b916001600160a01b038316156106295761059181866105c6995f976105ab976133a3565b946105a560045463ffffffff9060a01c1690565b96612718565b60405180958192632f1c2cd560e21b8352866004840161253f565b0381305afa918215610624576105e3935f93610600575b50613681565b8051602091820151604080519283529282015290819081015b0390f35b61061d9193503d805f833e6106158183610c6a565b810190612517565b915f6105dd565b612563565b622dc1c960e71b5f5260045ffd5b5f9103126103ca57565b346103ca575f3660031901126103ca57602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346103ca5760203660031901126103ca5760043561069e816103b9565b60018060a01b03165f526005602052602060405f205460601c604051908152f35b60609060031901126103ca57600490565b60609060631901126103ca57606490565b9181601f840112156103ca578235916001600160401b0383116103ca57602083818601950101116103ca57565b60e03660031901126103ca57610723366106bf565b6064356084356001600160401b0381116103ca576107459036906004016106e1565b9060a43592610753846103b9565b60c4356001600160401b0381116103ca576107729036906004016106e1565b5050337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316036107f9578435946107b0866108f7565b6107b986613748565b9560208201358097036107d357506107d195506137bf565b005b63ffffffff816107e389936108f7565b63309afaf360e21b5f521660045260245260445ffd5b6391ac5e4f60e01b5f523360045260245ffd5b346103ca575f3660031901126103ca57604080516001815260026020820152f35b346103ca5760203660031901126103ca576004355f52600a602052602060405f2054604051908152f35b346103ca5760203660031901126103ca5760206108826004355f526003602052600160405f20015490565b604051908152f35b346103ca575f3660031901126103ca5760206040516c3607fce1ac9e043a86675c5c2f8152f35b346103ca5760403660031901126103ca576107d16024356004356108d4826103b9565b6108f26108ed825f526003602052600160405f20015490565b613988565b6139c2565b63ffffffff8116036103ca57565b346103ca5760403660031901126103ca576107d1600435610925816108f7565b60243590610931613a52565b613a78565b346103ca5760403660031901126103ca57600435602435610956816103b9565b336001600160a01b0382160361096f576107d191613abe565b63334bd91960e11b5f5260045ffd5b346103ca575f3660031901126103ca576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346103ca5760203660031901126103ca576004356109df816103b9565b60018060a01b03165f526009602052602060ff60405f2054166040519015158152f35b60806003198201126103ca57600435610a1a816108f7565b91602435610a27816103b9565b91604435906001600160401b0382116103ca57610a4691600401610472565b90916064356001600160801b03811681036103ca5790565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b346103ca576105fc610a9f610a9636610a02565b939290926125c8565b604051918291602083526020830190610a5e565b346103ca57610ac136610a02565b6001600160a01b038085165f9081526005602052604090209195949391610ae790610566565b1615610629576105c6945f926105ab9260405195610b1c87610b0e85858560208501612697565b03601f198101895288610c6a565b876125c8565b346103ca575f3660031901126103ca57602063ffffffff60045460a01c16604051908152f35b346103ca5760603660031901126103ca57600435610b65816103b9565b6024356001600160401b0381116103ca57610b84903690600401610472565b909190604435906001600160801b03821682036103ca576105fc93610a9f93612718565b6024359061ffff821682036103ca57565b359061ffff821682036103ca57565b90600182811c92168015610bf6575b6020831014610be257565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610bd7565b634e487b7160e01b5f52604160045260245ffd5b606081019081106001600160401b03821117610c2f57604052565b610c00565b60e081019081106001600160401b03821117610c2f57604052565b604081019081106001600160401b03821117610c2f57604052565b90601f801991011681019081106001600160401b03821117610c2f57604052565b9060405191825f825492610c9e84610bc8565b8084529360018116908115610d095750600114610cc5575b50610cc392500383610c6a565b565b90505f9291925260205f20905f915b818310610ced575050906020610cc3928201015f610cb6565b6020919350806001915483858901015201910190918492610cd4565b905060209250610cc394915060ff191682840152151560051b8201015f610cb6565b346103ca5760403660031901126103ca576105fc610a9f610d7c600435610d51816108f7565b63ffffffff610d5e610ba8565b91165f52600260205260405f209061ffff165f5260205260405f2090565b610c8b565b346103ca575f3660031901126103ca576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346103ca5760203660031901126103ca57600435610de2816103b9565b610dea613a52565b60014603610ece576004546001600160a01b0316610ebf57600480546001600160a01b0319166001600160a01b0383161790556c3607fce1ac9e043a86675c5c2f3b156103ca5760405163a22cb46560e01b81526001600160a01b0382166004820152600160248201525f81604481836c3607fce1ac9e043a86675c5c2f5af1801561062457610ea5575b506001600160a01b03167fb835fe32fb60b329ea744c781d0f1f6c73e746d5896560940444554cc0c275b55f80a2005b80610eb35f610eb993610c6a565b80610637565b5f610e75565b634dad647560e11b5f5260045ffd5b63057f3fa760e51b5f5260045ffd5b346103ca575f3660031901126103ca576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b6001600160401b038116036103ca57565b346103ca576101003660031901126103ca57600435610f50816108f7565b60243590604435610f6081610f21565b610f69366106d0565b9160c43560e4356001600160401b0381116103ca57610f8c9036906004016106e1565b909463ffffffff84169563fffff9be87116110ba57610fd392610fc5916040519586946304c98a8b60e51b6020870152602486016127e8565b03601f198101835282610c6a565b6040516020810190610feb81610fc54686308761284c565b5190206110318461101b8861100e8763ffffffff165f52600860205260405f2090565b905f5260205260405f2090565b906001600160401b03165f5260205260405f2090565b54036110ab575f61105b8461101b8861100e6110639763ffffffff165f52600860205260405f2090565b555a30613cc6565b90156110a357506040516001600160401b039190911681527f49a5bb7337668613a742dc30346f29d11f0b4d4a2c0745a08afccc9bb6cea3d090602090a3005b805190602001fd5b63a84ab60d60e01b5f5260045ffd5b634d30e69360e11b5f5260045ffd5b346103ca575f3660031901126103ca5760206040516001600160401b03197f0000000000000000000000000000000000000000000000000000000000000000168152f35b346103ca575f3660031901126103ca57611125613a52565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346103ca5760403660031901126103ca576111806004356108f7565b60206040515f8152f35b346103ca5760a03660031901126103ca576111a4366106bf565b506064356001600160401b0381116103ca576111c49036906004016106e1565b505060206084356111d4816103b9565b6040516001600160a01b0390911630148152f35b346103ca5760403660031901126103ca576107d1600435611208816103b9565b60243590611215826108f7565b61121d613a52565b60018060a01b03165f52600560205260405f209063ffffffff60401b82549160401b169063ffffffff60401b1916179055565b801515036103ca57565b346103ca5760203660031901126103ca577f57f2a528edf864f533774c287d06a5278e1a4447ed97923b7bbc251fcbd54f6f602060043561129a81611250565b6112a2613a52565b151560ff19600b541660ff821617600b55604051908152a1005b346103ca575f3660031901126103ca575f546040516001600160a01b039091168152602090f35b346103ca5760403660031901126103ca57602060ff61132960243560043561130a826103b9565b5f526003845260405f209060018060a01b03165f5260205260405f2090565b54166040519015158152f35b346103ca5760a03660031901126103ca5761134f366106bf565b6064356084356001600160401b0381116103ca576113719036906004016106e1565b909230330361149a5763ffffffff63fffff9be913561138f816108f7565b1611156113d2576107086113b56113ae845f52600a60205260405f2090565b5442613788565b116113c3576107d192614462565b631a86ecf960e01b5f5260045ffd5b826113e093925001906142fd565b6001600160a01b039283165f81815260056020526040902090939192909116905461140b8160601c90565b906001600160a01b038216156106295763ffffffff16460361143157506107d1926148c7565b5f93508392908390610fc59061147a9061145b906001600160a01b03165b6001600160a01b031690565b946040519283916020830196639277283360e01b885260248401614340565b51925af1611486614358565b506107d157635f0ad7b760e11b5f5260045ffd5b63139f696160e31b5f5260045ffd5b346103ca5760203660031901126103ca57602061ffff6114f663ffffffff6004356114d3816108f7565b1663ffffffff908060031c5f52600c60205260e060405f20549160051b161c1690565b16604051908152f35b346103ca575f3660031901126103ca5760206040515f8152f35b346103ca5760203660031901126103ca57600435611536816103b9565b60018060a01b03165f526005602052608060405f20546040519063ffffffff8116825263ffffffff8160201c16602083015263ffffffff8160401c16604083015260601c6060820152f35b346103ca5760403660031901126103ca577fc40a8c1d6db18d083249778a76a84a78429c4fe53001aba75f470c597afaee2760406004356115c1816108f7565b61ffff6115cc610ba8565b6115d4613a52565b16600c602052631fffffff8260031c165f52825f2060e08360051b168154908382821c1863ffffffff16901b18905563ffffffff8351921682526020820152a1005b346103ca5760603660031901126103ca57611677600435611636816108f7565b60243563ffffffff6044359261164b84610f21565b165f52600860205260405f20905f5260205260405f20906001600160401b03165f5260205260405f2090565b54604051908152602090f35b346103ca5760203660031901126103ca576004356001600160401b0381116103ca576116b3903690600401610472565b906116bc613a52565b6116c58261287a565b906116d36040519283610c6a565b828252602082019260051b8101903682116103ca5780935b8285106116fb576107d184613ec3565b84356001600160401b0381116103ca578201906060823603126103ca576040519161172583610c14565b8035611730816108f7565b835261173e60208201610bb9565b60208401526040810135906001600160401b0382116103ca57019036601f830112156103ca57602092611778849336908581359101612891565b60408201528152019401936116eb565b346103ca5760203660031901126103ca5763ffffffff6004356117aa816108f7565b165f526001602052602060405f2054604051908152f35b346103ca5760603660031901126103ca576004356117de816108f7565b6117e6610ba8565b604435906001600160401b0382116103ca576105fc9261180d610a9f9336906004016106e1565b929091612929565b346103ca5760403660031901126103ca5761183e600435611835816103b9565b602435906129fc565b604080516001600160a01b03939093168352901515602083015290f35b60c03660031901126103ca57600435611873816108f7565b60243590611880826103b9565b6044356001600160401b0381116103ca5761189f903690600401610472565b606492919235906118af826103b9565b608435916118bc836103b9565b6118c46104b8565b906001600160a01b03811615611b1b5763ffffffff85169463ffffffff7f00000000000000000000000000000000000000000000000000000000000000001686148015611b0e575b6110ba578315611aff576001600160a01b0388165f9081526005602052604090209261194a61194561193f865460601c90565b95612578565b613fbd565b15611ace57889291906001600160a01b0385165f5b878110611a5a575050905f6119a06119bb935b888c6040519861199a8a61198c85858d86602086016126bf565b03601f1981018c528b610c6a565b866125c8565b60405180948192632f1c2cd560e21b8352856004840161253f565b0381305afa968715610624577f6a0cf129b799c36943cf19ef7755eafb0b597737ba2f970045385de48107886a97611a3995611a1b945f92611a3e575b50611a0161246b565b3481525f60208201526001600160a01b039093169361403f565b506040516001600160a01b0393841698909316969293849384612cd0565b0390a4005b611a539192503d805f833e6106158183610c6a565b905f6119f8565b909192939450611a6b81888c612cbb565b3590823b156103ca576040516323b872dd60e01b815233600482015230602482015260448101929092525f8260648183875af191821561062457600192611aba575b5001908a9493929161195f565b80610eb35f611ac893610c6a565b5f611aad565b9091906001600160a01b0384163303611af05788925f6119a06119bb93611972565b6348f5c3ed60e01b5f5260045ffd5b630f59b9ff60e01b5f5260045ffd5b5063fffff9be861161190c565b63d721852160e01b5f5260045ffd5b346103ca575f60203660031901126103ca57600435611b48816103b9565b611b50613a52565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b156103ca5760405163ca5eb5e160e01b81526001600160a01b039091166004820152905f908290602490829084905af1801561062457611bbb575080f35b6107d191505f90610c6a565b346103ca5760403660031901126103ca577f69bdfca1ae414a7233840909f9c10a21560d38e0ed4fb50ff50b7b4c29ad96fe600435611c05816103b9565b60243590611c1282611250565b611c1a613a52565b6001600160a01b03165f81815260096020908152604091829020805460ff191660ff9515159586161790558151928352820192909252a1005b346103ca5760203660031901126103ca57600435611c70816108f7565b611c78613a52565b63ffffffff81169063fffff9be821115611cdd576004805463ffffffff60a01b191660a09290921b63ffffffff60a01b169190911790556040519081527fd22acca42bfd0ebef8a1ca8347653f46f782b92b553ba57e0f2294426dfe26ac90602090a1005b633df6e48d60e21b5f5260045ffd5b346103ca5760403660031901126103ca576107d1602435600435611d0f826103b9565b611d286108ed825f526003602052600160405f20015490565b613abe565b346103ca5760a03660031901126103ca57600435611d4a816103b9565b602435611d56816108f7565b60443591611d63836103b9565b60643590611d70826108f7565b60843592611d7d846108f7565b611d85613919565b63ffffffff8116928315610ece5763ffffffff81169586156110ba576001600160a01b038116958615611fbe576001600160a01b038516958615611fbe57627a120063ffffffff831611611faf574603611f735763ffffffff7f00000000000000000000000000000000000000000000000000000000000000001688036110ba57868603611f64575b6001600160a01b0382165f908152600560205260409020611e329061144f90610566565b611f555784611eb6611ec692611ea9611edf96611e8587611e66611f2f9c60018060a01b03165f52600660205260405f2090565b80546001600160a01b0319166001600160a01b03909216919091179055565b611e9c611e9061247a565b63ffffffff909a168a52565b63ffffffff166020890152565b63ffffffff166040870152565b6001600160a01b03166060850152565b6001600160a01b03165f90815260056020526040902090565b8151602080840151604080860151606096870151911b63ffffffff60401b1663ffffffff9094169190921b67ffffffff000000001617919091176001600160601b03199190931b16919091179055565b7f328b68290d8d3a315d25b2476661d7c921ee87029fc767a4916b407e2ee31ede5f80a4005b6341ab882d60e01b5f5260045ffd5b630232505d60e61b5f5260045ffd5b63ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168803611e0e57634d30e69360e11b5f5260045ffd5b634a11e78360e11b5f5260045ffd5b63d92e233d60e01b5f5260045ffd5b346103ca575f3660031901126103ca5760206040517f8970ff45bc1804c7a79662cce9df9b0403588be8e486c6f5a410a2814caa892c8152f35b346103ca5760403660031901126103ca576004356001600160401b0381116103ca576120379036906004016106e1565b602435906001600160401b0382116103ca576105fc9261205e610a9f9336906004016106e1565b929091612d58565b346103ca5760403660031901126103ca576004356001600160401b0381116103ca576120969036906004016106e1565b602435906001600160401b0382116103ca576105fc926120bd610a9f933690600401610472565b929091613044565b346103ca5760403660031901126103ca576107d16004356120e5816108f7565b6024356120f181611250565b6120f9613a52565b15612105573090613a78565b5f90613a78565b346103ca5760203660031901126103ca57600435612129816103b9565b60018060a01b03165f526006602052602060018060a01b0360405f205416604051908152f35b346103ca575f3660031901126103ca57602060ff600b54166040519015158152f35b346103ca5760203660031901126103ca5760043561218e816103b9565b612196613a52565b6001600160a01b031680156121e7575f80546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b5f525f60045260245ffd5b346103ca575f3660031901126103ca576004546040516001600160a01b039091168152602090f35b60a03660031901126103ca5760043561223a816103b9565b6024356001600160401b0381116103ca57612259903690600401610472565b6044356001600160401b0381116103ca57612278903690600401610472565b9360643594612286866103b9565b61228e6104ce565b918415801561241e575b611aff576001600160a01b0381165f908152600560205260409020805460601c95908615610629576122cf6119456122d392612578565b1590565b806123c3575b6123b4576122ea81888588866133a3565b906123295f61230e61230560045463ffffffff9060a01c1690565b97848c88612718565b60405180938192632f1c2cd560e21b83528a6004840161253f565b0381305afa958615610624576105fc9a7fed0c24299d2da4e3728deedbf20de24c4ff0e754c89f20b3d2532fe63b43b531976123a195612372945f92611a3e5750611a0161246b565b5197426123878a5f52600a60205260405f2090565b556040516001600160a01b0390941696939485948561327b565b0390a36040519081529081906020820190565b634a91ec5f60e01b5f5260045ffd5b50604051637347ebb960e01b81526020816004818a5afa908115610624575f916123ef575b50156122d9565b612411915060203d602011612417575b6124098183610c6a565b8101906129d2565b5f6123e8565b503d6123ff565b508115612298565b346103ca5760603660031901126103ca576020612442366106bf565b63ffffffff8135612452816108f7565b165f52600182528160405f205491013560405191148152f35b60405190610cc3604083610c6a565b60405190610cc3608083610c6a565b60405190610cc360e083610c6a565b60405190610cc360c083610c6a565b60405190610cc360a083610c6a565b6001600160401b038111610c2f57601f01601f191660200190565b81601f820112156103ca578051906124e8826124b6565b926124f66040519485610c6a565b828452602083830101116103ca57815f9260208093018386015e8301015290565b906020828203126103ca5781516001600160401b0381116103ca5761253c92016124d1565b90565b60609063ffffffff61253c9493168152600160208201528160408201520190610a5e565b6040513d5f823e3d90fd5b3561253c816108f7565b90604051608081018181106001600160401b03821117610c2f57604052606081935463ffffffff8116835263ffffffff8160201c16602084015263ffffffff8160401c166040840152811c910152565b929150926126069360018060a01b03165f52600560205263ffffffff60406125f1815f20612578565b94828060208801511691161494015116613b66565b9061260f613bce565b91600361ffff61261e856141db565b16036126545761253c9192604051916001600160801b03199060801b1660208301526010825261264f603083610c6a565b614227565b61ffff612660846141db565b633a51740d60e01b5f521660045260245ffd5b81835290916001600160fb1b0383116103ca5760209260051b809284830137010190565b6001600160a01b0390911681525f602082015260606040820181905261253c93910191612673565b6001600160a01b0391821681529116602082015260606040820181905261253c93910191612673565b634e487b7160e01b5f52601160045260245ffd5b63ffffffff1660e0019063ffffffff821161271357565b6126e8565b61276f9293915060018060a01b03165f5260056020526001600160801b0363ffffffff61274760405f20612578565b51164614805f146127be576201adb0905b156127b557816206390e5b81871602160116613b46565b90627a12006001600160801b03831611611faf5763ffffffff166060029063ffffffff8216918203612713576127a761253c926126fc565b906127b0613bce565b613bea565b8161c350612763565b6201b7d890612758565b908060209392818452848401375f828201840152601f01601f1916010190565b61253c94926001600160401b03604060a09463ffffffff813561280a816108f7565b16855260208101356020860152013561282281610f21565b166040830152606082015281608082015201916127c8565b805191908290602001825e015f815290565b91601460209493612873936bffffffffffffffffffffffff199060601b168152019061283a565b9081520190565b6001600160401b038111610c2f5760051b60200190565b92919261289d826124b6565b916128ab6040519384610c6a565b8294818452818301116103ca578281602093845f960137010152565b90606e116103ca57602e0190604090565b906054116103ca5760400190601490565b6129039392610cc39281604051968794602086019061283a565b918237015f815203601f198101845283610c6a565b91602061253c9381815201916127c8565b6129579163ffffffff610d7c9296949596165f52600260205260405f209061ffff165f5260205260405f2090565b8051156129c45783156129be57600284101561298f57505061298b604051928392639a6d49cd60e01b845260048401612918565b0390fd5b90926129a461299f368386612891565b613f85565b806002116103ca57600261253c93019060011901916128e9565b92509050565b50919061253c913691612891565b908160209103126103ca575161253c81611250565b908160209103126103ca575161253c816103b9565b6001600160a01b03165f908152600560205260409020612a2090612578565b612578565b63ffffffff612a36602083015163ffffffff1690565b1615612c9e57612a5e6060612a4f835163ffffffff1690565b9201516001600160a01b031690565b9063ffffffff164603612bc2576040516331a9108f60e11b8152600481018390526020816024816001600160a01b0386165afa5f9181612ba1575b50612aa7575050505f905f90565b6001600160a01b0381163003612ac1575050503090600190565b612b2991602091935b604051637f63c3dd60e01b81526001600160a01b039092166004830152602482015267ffffffffffffffff197f000000000000000000000000000000000000000000000000000000000000000016604482015291829081906064820190565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa5f9181612b70575b50612b6a5750905f90565b915f9150565b612b9391925060203d602011612b9a575b612b8b8183610c6a565b8101906129e7565b905f612b5f565b503d612b81565b612bbb91925060203d602011612b9a57612b8b8183610c6a565b905f612a99565b6001600160a01b03811680158015612c4d575b15612be4575050505f90600190565b612b29916020918260405180926331a9108f60e11b82528180612c0f8a600483019190602083019252565b03915afa5f9181612c2e575b50612c2857505f93612aca565b93612aca565b612c46919250843d8611612b9a57612b8b8183610c6a565b905f612c1b565b50604051635a2d1e0760e11b815260048101849052602081602481855afa908115610624575f91612c7f575b50612bd5565b612c98915060203d602011612417576124098183610c6a565b5f612c79565b50505f90600190565b634e487b7160e01b5f52603260045260245ffd5b9190811015612ccb5760051b0190565b612ca7565b91602091612ce991959495604085526040850191612673565b6001600160a01b03909416910152565b91908260409103126103ca5760208235612d12816103b9565b92013590565b91908260409103126103ca5760208235612d31816103b9565b92013561253c81611250565b60405190612d4c602083610c6a565b5f808352366020840137565b612d6b612d8892612d73929594956128c7565b810190612cf9565b936001600160a01b0390911692810190612d18565b612ea2578183612dae612a1b61253c9560018060a01b03165f52600560205260405f2090565b91612db883613fbd565b15612e24576001600160a01b03165f908152600760205260409020610fc59250612df291612de59161100e565b546001600160a01b031690565b935b604080516001600160a01b0396871660208201529590931692850192909252606084019190915282906080820190565b505060600151612e3e9061144f906001600160a01b031681565b6040516331a9108f60e11b81526004810185905290602090829060249082905afa5f9181612e81575b50612e775750610fc55f93612df4565b610fc59093612df4565b612e9b91925060203d602011612b9a57612b8b8183610c6a565b905f612e67565b50505061253c612d3d565b356001600160601b0319811692919060148210612ec8575050565b6001600160601b031960149290920360031b82901b16169150565b90612eed8261287a565b612efa6040519182610c6a565b8281528092612f0b601f199161287a565b0190602036910137565b9190811015612ccb5760051b81013590601e19813603018212156103ca5701908135916001600160401b0383116103ca5760200182360381136103ca579190565b908160609103126103ca578035612f6c816103b9565b9160406020830135612d12816103b9565b8051821015612ccb5760209160051b010190565b90602080835192838152019201905f5b818110612fae5750505090565b82516001600160a01b0316845260209384019390920191600101612fa1565b90602080835192838152019201905f5b818110612fea5750505090565b8251845260209384019390920191600101612fdd565b9261302861253c95936130369360018060a01b03168652608060208701526080860190612f91565b908482036040860152612f91565b916060818403910152612fcd565b61306f612a1b611ec661306961306361307d966060969a99989a6128d8565b90612ead565b60601c90565b01516001600160a01b031690565b61308682612ee3565b9161309081612ee3565b9461309a82612ee3565b915f915f5b82811061318357505050815181106130cb5750610fc59061253c93949560405195869460208601613000565b92906130d684612ee3565b936130e081612ee3565b916130ea82612ee3565b935f5b838110613113575050505061253c9394955090610fc59160405195869460208601613000565b8061316761315d613136838e6131588e6131498461314361313660019c8e612f7d565b516001600160a01b031690565b92612f7d565b6001600160a01b039091169052565b612f7d565b6131498389612f7d565b6131718185612f7d565b5161317c8289612f7d565b52016130ed565b61318e818484612f15565b905015613273576131e8816131d58b613149838a6131c56131bb6131b3848d8d612f15565b810190612f56565b9291989093612f7d565b526001600160a01b031692612f7d565b6001600160a01b0316613149838a612f7d565b6131f56131368289612f7d565b61320561144f613136848d612f7d565b6001600160a01b0390911603613220575b6001905b0161309f565b926001809161322f8688612f7d565b5161323a8289612f7d565b5261325561324b613136888c612f7d565b613149838c612f7d565b61326a8b613149836131436131368b85612f7d565b01939050613216565b60019061321a565b949391949290928560408201604083525260608101935f965b8088106132b057505061253c9495506020818503910152612673565b909460208060019263ffffffff89356132c8816108f7565b16815201960197019690613294565b908160011b918083046002149015171561271357565b8181029291811591840414171561271357565b9061330a8261287a565b6133176040519182610c6a565b8281528092613328601f199161287a565b01905f5b82811061333857505050565b60209060405161334781610c34565b5f81525f838201525f60408201525f60608201525f60808201525f60a0820152606060c08201528282850101520161332c565b906001820180921161271357565b906023820180921161271357565b9190820180921161271357565b9391926133b86133b385856132ed565b613300565b935f956001600160401b034216965b85811061343c575050505050509061253c9161342b6133e4612498565b600281529263ffffffff7f00000000000000000000000000000000000000000000000000000000000000001660208501525f60408501526001600160401b03166060840152565b5f60808301523060a083015261413b565b5f5b83811061344e57506001016133c7565b61349261347061346761346284888b612cbb565b61256e565b63ffffffff1690565b63ffffffff908060031c5f52600c60205260e060405f20549160051b161c1690565b63ffffffff8116156110ba57836134a88461337a565b6134b28a856132ed565b6134bb91613396565b61ffff16916134cb84888b612cbb565b6134d49061256e565b906134e085898c612cbb565b6134e99061256e565b6134f290613748565b6001600160a01b031691613507878d8c612cbb565b604051635ed34d0560e11b60208201526001600160a01b0395909516602486015235604480860191909152845261353f606485610c6a565b613547612489565b61ffff909516855263ffffffff1660208501525f60408501526001600160401b038d16606085015261ffff1660808401526001600160a01b031660a083015260c08201528161359686856132ed565b906135a091613396565b906135ab828b612f7d565b526135b69089612f7d565b5060010161343e565b604051906135cc82610c4f565b5f6020838281520152565b91908260409103126103ca576040516135ef81610c4f565b6020808294805184520151910152565b906040828203126103ca5761253c916135d7565b906020909392936040835263ffffffff81511660408401528181015160608401526080613667613651604084015160a08488015260e0870190610a5e565b6060840151868203603f190160a0880152610a5e565b910151151560c08401526001600160a01b03909416910152565b6136e0926040926136906135bf565b5061369a83613748565b6136b16136a56124a7565b63ffffffff9095168552565b60208401528383015260608201525f6080820152815180938192631bb8518b60e31b8352309060048401613613565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610624575f9161371f575090565b61253c915060403d604011613741575b6137398183610c6a565b8101906135ff565b503d61372f565b63ffffffff16805f52600160205260405f2054908115613766575090565b63f6ff4fb760e01b5f5260045260245ffd5b61c34f1981019190821161271357565b9190820391821161271357565b3561253c81610f21565b6040906001600160401b0361253c94931681528160208201520190610a5e565b939291926137cf600b5460ff1690565b90816138f7575b506138e857610fc56137ff926040519485936304c98a8b60e51b602086015287602486016127e8565b6138128161380c5a613778565b30613cc6565b91901561381e57505050565b63ffffffff7fd191660d5fb7fa40de3038f810fa899670f44a26d29f0609702b778de1c4e5f69160405161385d81610fc560208201944690308761284c565b5190206138e36138d46138ce6138896138758961256e565b63ffffffff165f52600860205260405f2090565b976138a16020820135809a905f5260205260405f2090565b946138c860408301966138b388613795565b6001600160401b03165f5260205260405f2090565b5561256e565b92613795565b9460405193849316958361379f565b0390a3565b6341c8302160e11b5f5260045ffd5b6001600160a01b03165f9081526009602052604081205460ff161591506137d6565b335f9081527f460e1c17541eb4600da639136d22ecdece50dfd5504d40fe2d419370e887d378602052604090205460ff161561395157565b63e2517d3f60e01b5f52336004527f8970ff45bc1804c7a79662cce9df9b0403588be8e486c6f5a410a2814caa892c60245260445ffd5b5f81815260036020908152604080832033845290915290205460ff16156139ac5750565b63e2517d3f60e01b5f523360045260245260445ffd5b5f8181526003602090815260408083206001600160a01b038616845290915290205460ff16613a4c575f8181526003602090815260408083206001600160a01b03861684529091529020805460ff1916600117905533916001600160a01b0316907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b5f546001600160a01b03163303613a6557565b63118cdaa760e01b5f523360045260245ffd5b7f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b9163ffffffff6040921690815f52600160205280835f205582519182526020820152a1565b5f8181526003602090815260408083206001600160a01b038616845290915290205460ff1615613a4c575f8181526003602090815260408083206001600160a01b03861684529091529020805460ff1916905533916001600160a01b0316907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b906001600160801b03809116911601906001600160801b03821161271357565b916001600160801b03613b9e948193948180613bc3575b15613bb957905b15613bb45762031c870181165b16026201adb00116613b46565b90627a12006001600160801b03831611611faf57565b613b91565b5061c35090613b84565b508281161515613b7d565b604051600360f01b60208201526002815261253c602282610c6a565b91600361ffff613bf9856141db565b16036126545760405160809290921b6fffffffffffffffffffffffffffffffff1916602083015260e01b6001600160e01b031916603082015260148152613c41603482610c6a565b600361ffff613c4f846141db565b1603613cba57600161ffff613c6483516148a0565b16019161ffff831161271357610fc561253c926004613c8d95604051968795602087019061283a565b600160f81b815260f09190911b6001600160f01b0319166001820152600560f81b6003820152019061283a565b61ffff612660836141db565b92915f9190829182613cd860046124b6565b96613ce66040519889610c6a565b60048852601f19613cf760046124b6565b013660208a013760208451940192f13d60048111613d1d575b8084525f602085013e9190565b506004613d10565b601f8211613d3257505050565b5f5260205f20906020601f840160051c83019310613d6a575b601f0160051c01905b818110613d5f575050565b5f8155600101613d54565b9091508190613d4b565b91909182516001600160401b038111610c2f57613d9b81613d958454610bc8565b84613d25565b6020601f8211600114613dda578190613dcb9394955f92613dcf575b50508160011b915f199060031b1c19161790565b9055565b015190505f80613db7565b601f19821690613ded845f5260205f2090565b915f5b818110613e2757509583600195969710613e0f575b505050811b019055565b01515f1960f88460031b161c191690555f8080613e05565b9192602060018192868b015181550194019201613df0565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310613e7157505050505090565b9091929394602080613eb4600193603f19868203018752606060408b5163ffffffff815116845261ffff8682015116868501520151918160408201520190610a5e565b97019301930191939290613e62565b5f5b8151811015613f4e5780613ee86040613ee060019486612f7d565b510151613f85565b613f486040613ef78386612f7d565b51015163ffffffff613f098487612f7d565b5151165f526002602052613f4360405f20613f336020613f29878a612f7d565b51015161ffff1690565b61ffff165f5260205260405f2090565b613d74565b01613ec5565b50613f807fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b6749160405191829182613e3f565b0390a1565b600361ffff60028301511603613f985750565b604051639a6d49cd60e01b81526020600482015290819061298b906024830190610a5e565b63ffffffff815116156106295763ffffffff905116461490565b60405190613fe482610c14565b815f81525f60208201526040613ff86135bf565b910152565b906080828203126103ca5761403790604080519361401a85610c14565b80518552602081015161402c81610f21565b6020860152016135d7565b604082015290565b6140a8608094926140c49694614053613fd7565b5060206140608651614693565b95019182518061412c575b5061407585613748565b92511515926140916140856124a7565b63ffffffff9097168752565b602086015260408501526060840152151585830152565b6040518095819482936302637a4560e41b845260048401613613565b03917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af1908115610624575f91614103575090565b61253c915060803d608011614125575b61411d8183610c6a565b810190613ffd565b503d614113565b614135906146b0565b5f61406b565b91909161414881516148a0565b604051600160f01b60208201525f602282015260f09190911b6001600160f01b03191660248201526006815261417f602682610c6a565b915f925b82518410156141ab576141a360019161419c8686612f7d565b5190614e49565b930192614183565b92509290508163ffffffff6141c7602084015163ffffffff1690565b166141d157505090565b61253c92506147b8565b60028151106141eb576002015190565b60405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606490fd5b90600361ffff614236846141db565b1603613cba57600161ffff61424b83516148a0565b16019161ffff831161271357610fc561253c92600461427495604051968795602087019061283a565b600160f81b80825260f09290921b6001600160f01b03191660018201526003810191909152019061283a565b9080601f830112156103ca5781356142b78161287a565b926142c56040519485610c6a565b81845260208085019260051b8201019283116103ca57602001905b8282106142ed5750505090565b81358152602091820191016142e0565b916060838303126103ca578235614313816103b9565b926020810135614322816103b9565b9260408201356001600160401b0381116103ca5761253c92016142a0565b90612ce9602091949394604084526040840190612fcd565b3d15614382573d90614369826124b6565b916143776040519384610c6a565b82523d5f602084013e565b606090565b9080601f830112156103ca57813561439e8161287a565b926143ac6040519485610c6a565b81845260208085019260051b8201019283116103ca57602001905b8282106143d45750505090565b6020809183356143e3816103b9565b8152019101906143c7565b906080828203126103ca578135614404816103b9565b9260208301356001600160401b0381116103ca5782614424918501614387565b9260408101356001600160401b0381116103ca5783614444918301614387565b9260608201356001600160401b0381116103ca5761253c92016142a0565b614471919392938101906143ee565b6001600160a01b039093165f81815260066020526040902091929161449590612de5565b916144b6611945612a1b8560018060a01b03165f52600560205260405f2090565b156144c8575050610cc3939450614aa1565b9150935f5b8451811015614647575f806144e56131368487612f7d565b6144f26131368589612f7d565b906144fd858a612f7d565b51906001600160a01b03811615841461457457506040516340c10f1960e01b602082019081526001600160a01b03909316602482015260448101919091526145488160648101610fc5565b5190828a5af1614556614358565b5015614566576001905b016144cd565b62ec6f7b60e31b5f5260045ffd5b916001600160a01b0381161584146145dc5750604051630852cd8d60e31b6020820190815260248201929092529091506145b18160448101610fc5565b5190828a5af16145bf614358565b50156145cd57600190614560565b631bc5aabf60e21b5f5260045ffd5b6040516323b872dd60e01b602082019081526001600160a01b039485166024830152939091166044820152606481019190915261461c8160848101610fc5565b5190828a5af161462a614358565b501561463857600190614560565b6312171d8360e31b5f5260045ffd5b50949392505050803b156103ca5760405163163b5cc360e31b815260048101929092525f908290602490829084905af1801561062457614685575b50565b80610eb35f610cc393610c6a565b80340361469d5790565b6304fb820960e51b5f523460045260245ffd5b60405163393f876560e21b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690602081600481855afa908115610624575f91614799575b506001600160a01b031691821561478a576040516323b872dd60e01b60208281019182523360248401526001600160a01b03909416604483015260648201929092525f91906147518160848101610fc5565b519082855af115612563575f513d6147815750803b155b61476f5750565b635274afe760e01b5f5260045260245ffd5b60011415614768565b6329b99a9560e11b5f5260045ffd5b6147b2915060203d602011612b9a57612b8b8183610c6a565b5f6146ff565b61253c9060276148149361489160ff8251169163ffffffff60208201511690604081015115156001600160401b036060830151169061ffff6080840151169260a0600180821b0391015116936040519a8b9960208b019061283a565b600160f81b8152600160f01b600182015260f897881b6001600160f81b031916600382015260e09190911b6001600160e01b031916600482015290151590951b600886015260c01b6001600160c01b031916600985015260f01b6001600160f01b031916601184015260601b6001600160601b0319166013830152565b0103601f198101835282610c6a565b61ffff81116148b05761ffff1690565b6306dfcc6560e41b5f52601060045260245260445ffd5b5f5b8351811015614953576001600160a01b0382166148e68286612f7d565b5190803b156103ca576040516323b872dd60e01b81523060048201526001600160a01b038616602482015260448101929092525f908290606490829084905af180156106245761493a575b506001016148c9565b806149465f8093610c6a565b8003126103ca575f614931565b50610cc3929150614ee8565b906149698261287a565b6149766040519182610c6a565b8281528092614987601f199161287a565b01905f5b82811061499757505050565b80606060208093850101520161498b565b6020818303126103ca578051906001600160401b0382116103ca57019080601f830112156103ca5781516149db8161287a565b926149e96040519485610c6a565b81845260208085019260051b820101918383116103ca5760208201905b838210614a1557505050505090565b81516001600160401b0381116103ca57602091614a37878480948801016124d1565b815201910190614a06565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310614a7457505050505090565b9091929394602080614a92600193603f198682030187528951610a5e565b97019301930191939290614a65565b909291614ab6614ab182516132d7565b61495f565b6004545f9390614ace906001600160a01b031661144f565b6001600160a01b03821696908703614d93576c3607fce1ac9e043a86675c5c2f905b5f955b8551871015614cd457614b096131368884612f7d565b9689614b158289612f7d565b5198614b5f60208b614b3e612de58261100e8d60018060a01b03165f52600760205260405f2090565b9460405180809581946331a9108f60e11b8352600483019190602083019252565b03915afa908115610624575f91614cb6575b50306001600160a01b0390911603614ca757611e66600180958c8b8a614c2597858060a01b038116614c2c575b505060405163b18e2bbb60e01b60208201526001600160a01b0380881660248301528c16604482015260648101929092525064ffffffffff6084820152600160a4820152614bef8160c48101610fc5565b614bf9828d612f7d565b52614c04818c612f7d565b506001600160a01b038a165f90815260076020526040902091019b9061100e565b0195614af3565b60405163b18e2bbb60e01b60208201526001600160a01b039182166024820152911660448201526064810183905264ffffffffff60848201525f60a48201529192610fc592614bef92869291614c99918391614c898160c481018a565b614c938383612f7d565b52612f7d565b5001929150508b8a5f614b9e565b6349e27cff60e01b5f5260045ffd5b614cce915060203d8111612b9a57612b8b8183610c6a565b5f614b71565b955050505092935050614ce68161495f565b915f5b828110614d69575050505f614d129160405180938192631592ca1b60e31b835260048301614a42565b0381837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af1801561062457614d4e5750565b614682903d805f833e614d618183610c6a565b8101906149a8565b80614d7660019284612f7d565b51614d818287612f7d565b52614d8c8186612f7d565b5001614ce9565b8190614af0565b614da990600b9593949261283a565b600160f81b815260f093841b6001600160f01b03199081166001830152600160f01b60038301529190931b16600583015260e01b6001600160e01b03191660078201520190565b92614e0461253c97969394601f969361283a565b93151560f81b845260c01b6001600160c01b031916600184015260f01b6001600160f01b031916600983015260601b6001600160601b031916600b820152019061283a565b9061253c90610fc5614e5d825161ffff1690565b91614ea560c0820195614e97614e7c614e77895151613388565b6148a0565b602085015163ffffffff169060405197889460208601614d9a565b03601f198101855284610c6a565b6040810151151594614ec160608301516001600160401b031690565b91614ed660a0612a4f608084015161ffff1690565b91519260405197889660208801614df0565b919091614ef5835161495f565b600454614f0a906001600160a01b031661144f565b6001600160a01b03831603615024576c3607fce1ac9e043a86675c5c2f935b5f5b8151811015614ffe5780614ff8614fe8614f4760019486612f7d565b5189614fb6614f6d612de58461100e8d60018060a01b03165f52600760205260405f2090565b60405163b18e2bbb60e01b60208201526001600160a01b039182166024820152921660448301526064820183905264ffffffffff60848301525f60a48301528160c48101610fc5565b614fc08589612f7d565b52614fcb8488612f7d565b506001600160a01b0388165f90815260076020526040902061100e565b80546001600160a01b0319169055565b01614f2b565b5050604051631592ca1b60e31b81529293505f915082908190614d129060048301614a42565b8193614f2956fea2646970667358221220fee52d7311955066f78324771ae7deefd5385e3abd4f8b126ddc67bfc595206764736f6c634300081c00332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d460e1c17541eb4600da639136d22ecdece50dfd5504d40fe2d419370e887d3783617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b000000000000000000000000000000000000506aa8bc5da44f9b3329b8c6f7e000000000000000000000000058a766b3210cee94ca150f767d842eb87a8d7ae800000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000447e69651d841bd8d104bed4930000000000000000000000000000000000007129af73c46c9f01a3fb4ff61a02
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c806301a0de05146103b457806301ffc9a7146103af57806304bd49a5146103aa578063066d5910146103a5578063108dcbdd146103a057806313137d651461039b57806317442b70146103965780631d56672114610391578063248a9ca31461038c5780632d69fc48146103875780632f2ff15d146103825780633400288b1461037d57806336568abe1461037857806336b1dd211461037357806337cb67361461036e5780634202fce11461036957806345248a3714610364578063461572f91461035f57806347c1b3171461035a5780635535d461146103555780635e280f111461035057806360eddbe41461034b5780636a4d8672146103465780636eaa6904146103415780636fe87dba1461033c578063715018a6146103375780637d25a05e1461033257806382413eac1461032d578063864c651514610328578063881ae9f8146103235780638da5cb5b1461031e57806391d14854146103195780639931516014610314578063a0238f3e1461030f578063a217fddf1461030a578063a34ac81b14610305578063ade7142d14610300578063b33b522d146102fb578063b98bd070146102f6578063bb0b6a53146102f1578063bc70b354146102ec578063bda69a0a146102e7578063c9df8167146102e2578063ca5eb5e1146102dd578063cfac96ce146102d8578063d1e1d0cc146102d3578063d547741f146102ce578063da383b97146102c9578063e052778a146102c4578063e60c287c146102bf578063eba1cf08146102ba578063f0a9e481146102b5578063f1748835146102b0578063f1c418ee146102ab578063f2fde38b146102a6578063fccc4331146102a1578063fe084c8f1461029c5763ff7bd03d14610297575f80fd5b612426565b612222565b6121fa565b612171565b61214f565b61210c565b6120c5565b612066565b612007565b611fcd565b611d2d565b611cec565b611c53565b611bc7565b611b2a565b61185b565b611815565b6117c1565b611788565b611683565b611616565b611581565b611519565b6114ff565b6114a9565b611335565b6112e3565b6112bc565b61125a565b6111e8565b61118a565b611164565b61110d565b6110c9565b610f32565b610edd565b610dc5565b610d81565b610d2b565b610b48565b610b22565b610ab3565b610a82565b6109c2565b61097e565b610936565b610905565b6108b1565b61088a565b610857565b61082d565b61080c565b61070e565b610681565b610641565b6104e4565b61041c565b6103ce565b6001600160a01b038116036103ca57565b5f80fd5b346103ca5760403660031901126103ca576004356103eb816103b9565b6001600160a01b039081165f9081526007602090815260408083206024358452825291829020549151919092168152f35b346103ca5760203660031901126103ca5760043563ffffffff60e01b81168091036103ca57602090637965db0b60e01b8114908115610461575b506040519015158152f35b6301ffc9a760e01b1490505f610456565b9181601f840112156103ca578235916001600160401b0383116103ca576020808501948460051b0101116103ca57565b606435906001600160801b03821682036103ca57565b60a435906001600160801b03821682036103ca57565b608435906001600160801b03821682036103ca57565b346103ca5760803660031901126103ca57600435610501816103b9565b6024356001600160401b0381116103ca57610520903690600401610472565b91906044356001600160401b0381116103ca57610541903690600401610472565b9361054a6104a2565b6001600160a01b0385165f90815260056020526040902061056d905b5460601c90565b916001600160a01b038316156106295761059181866105c6995f976105ab976133a3565b946105a560045463ffffffff9060a01c1690565b96612718565b60405180958192632f1c2cd560e21b8352866004840161253f565b0381305afa918215610624576105e3935f93610600575b50613681565b8051602091820151604080519283529282015290819081015b0390f35b61061d9193503d805f833e6106158183610c6a565b810190612517565b915f6105dd565b612563565b622dc1c960e71b5f5260045ffd5b5f9103126103ca57565b346103ca575f3660031901126103ca57602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000007668168152f35b346103ca5760203660031901126103ca5760043561069e816103b9565b60018060a01b03165f526005602052602060405f205460601c604051908152f35b60609060031901126103ca57600490565b60609060631901126103ca57606490565b9181601f840112156103ca578235916001600160401b0383116103ca57602083818601950101116103ca57565b60e03660031901126103ca57610723366106bf565b6064356084356001600160401b0381116103ca576107459036906004016106e1565b9060a43592610753846103b9565b60c4356001600160401b0381116103ca576107729036906004016106e1565b5050337f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0316036107f9578435946107b0866108f7565b6107b986613748565b9560208201358097036107d357506107d195506137bf565b005b63ffffffff816107e389936108f7565b63309afaf360e21b5f521660045260245260445ffd5b6391ac5e4f60e01b5f523360045260245ffd5b346103ca575f3660031901126103ca57604080516001815260026020820152f35b346103ca5760203660031901126103ca576004355f52600a602052602060405f2054604051908152f35b346103ca5760203660031901126103ca5760206108826004355f526003602052600160405f20015490565b604051908152f35b346103ca575f3660031901126103ca5760206040516c3607fce1ac9e043a86675c5c2f8152f35b346103ca5760403660031901126103ca576107d16024356004356108d4826103b9565b6108f26108ed825f526003602052600160405f20015490565b613988565b6139c2565b63ffffffff8116036103ca57565b346103ca5760403660031901126103ca576107d1600435610925816108f7565b60243590610931613a52565b613a78565b346103ca5760403660031901126103ca57600435602435610956816103b9565b336001600160a01b0382160361096f576107d191613abe565b63334bd91960e11b5f5260045ffd5b346103ca575f3660031901126103ca576040517f0000000000000000000000000000000000007129af73c46c9f01a3fb4ff61a026001600160a01b03168152602090f35b346103ca5760203660031901126103ca576004356109df816103b9565b60018060a01b03165f526009602052602060ff60405f2054166040519015158152f35b60806003198201126103ca57600435610a1a816108f7565b91602435610a27816103b9565b91604435906001600160401b0382116103ca57610a4691600401610472565b90916064356001600160801b03811681036103ca5790565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b346103ca576105fc610a9f610a9636610a02565b939290926125c8565b604051918291602083526020830190610a5e565b346103ca57610ac136610a02565b6001600160a01b038085165f9081526005602052604090209195949391610ae790610566565b1615610629576105c6945f926105ab9260405195610b1c87610b0e85858560208501612697565b03601f198101895288610c6a565b876125c8565b346103ca575f3660031901126103ca57602063ffffffff60045460a01c16604051908152f35b346103ca5760603660031901126103ca57600435610b65816103b9565b6024356001600160401b0381116103ca57610b84903690600401610472565b909190604435906001600160801b03821682036103ca576105fc93610a9f93612718565b6024359061ffff821682036103ca57565b359061ffff821682036103ca57565b90600182811c92168015610bf6575b6020831014610be257565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610bd7565b634e487b7160e01b5f52604160045260245ffd5b606081019081106001600160401b03821117610c2f57604052565b610c00565b60e081019081106001600160401b03821117610c2f57604052565b604081019081106001600160401b03821117610c2f57604052565b90601f801991011681019081106001600160401b03821117610c2f57604052565b9060405191825f825492610c9e84610bc8565b8084529360018116908115610d095750600114610cc5575b50610cc392500383610c6a565b565b90505f9291925260205f20905f915b818310610ced575050906020610cc3928201015f610cb6565b6020919350806001915483858901015201910190918492610cd4565b905060209250610cc394915060ff191682840152151560051b8201015f610cb6565b346103ca5760403660031901126103ca576105fc610a9f610d7c600435610d51816108f7565b63ffffffff610d5e610ba8565b91165f52600260205260405f209061ffff165f5260205260405f2090565b610c8b565b346103ca575f3660031901126103ca576040517f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03168152602090f35b346103ca5760203660031901126103ca57600435610de2816103b9565b610dea613a52565b60014603610ece576004546001600160a01b0316610ebf57600480546001600160a01b0319166001600160a01b0383161790556c3607fce1ac9e043a86675c5c2f3b156103ca5760405163a22cb46560e01b81526001600160a01b0382166004820152600160248201525f81604481836c3607fce1ac9e043a86675c5c2f5af1801561062457610ea5575b506001600160a01b03167fb835fe32fb60b329ea744c781d0f1f6c73e746d5896560940444554cc0c275b55f80a2005b80610eb35f610eb993610c6a565b80610637565b5f610e75565b634dad647560e11b5f5260045ffd5b63057f3fa760e51b5f5260045ffd5b346103ca575f3660031901126103ca576040517f00000000000000000000000000000000000000447e69651d841bd8d104bed4936001600160a01b03168152602090f35b6001600160401b038116036103ca57565b346103ca576101003660031901126103ca57600435610f50816108f7565b60243590604435610f6081610f21565b610f69366106d0565b9160c43560e4356001600160401b0381116103ca57610f8c9036906004016106e1565b909463ffffffff84169563fffff9be87116110ba57610fd392610fc5916040519586946304c98a8b60e51b6020870152602486016127e8565b03601f198101835282610c6a565b6040516020810190610feb81610fc54686308761284c565b5190206110318461101b8861100e8763ffffffff165f52600860205260405f2090565b905f5260205260405f2090565b906001600160401b03165f5260205260405f2090565b54036110ab575f61105b8461101b8861100e6110639763ffffffff165f52600860205260405f2090565b555a30613cc6565b90156110a357506040516001600160401b039190911681527f49a5bb7337668613a742dc30346f29d11f0b4d4a2c0745a08afccc9bb6cea3d090602090a3005b805190602001fd5b63a84ab60d60e01b5f5260045ffd5b634d30e69360e11b5f5260045ffd5b346103ca575f3660031901126103ca5760206040516001600160401b03197f502693d518cccccc945699ac6b0be7c02aef951c921558ec0000000000000000168152f35b346103ca575f3660031901126103ca57611125613a52565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346103ca5760403660031901126103ca576111806004356108f7565b60206040515f8152f35b346103ca5760a03660031901126103ca576111a4366106bf565b506064356001600160401b0381116103ca576111c49036906004016106e1565b505060206084356111d4816103b9565b6040516001600160a01b0390911630148152f35b346103ca5760403660031901126103ca576107d1600435611208816103b9565b60243590611215826108f7565b61121d613a52565b60018060a01b03165f52600560205260405f209063ffffffff60401b82549160401b169063ffffffff60401b1916179055565b801515036103ca57565b346103ca5760203660031901126103ca577f57f2a528edf864f533774c287d06a5278e1a4447ed97923b7bbc251fcbd54f6f602060043561129a81611250565b6112a2613a52565b151560ff19600b541660ff821617600b55604051908152a1005b346103ca575f3660031901126103ca575f546040516001600160a01b039091168152602090f35b346103ca5760403660031901126103ca57602060ff61132960243560043561130a826103b9565b5f526003845260405f209060018060a01b03165f5260205260405f2090565b54166040519015158152f35b346103ca5760a03660031901126103ca5761134f366106bf565b6064356084356001600160401b0381116103ca576113719036906004016106e1565b909230330361149a5763ffffffff63fffff9be913561138f816108f7565b1611156113d2576107086113b56113ae845f52600a60205260405f2090565b5442613788565b116113c3576107d192614462565b631a86ecf960e01b5f5260045ffd5b826113e093925001906142fd565b6001600160a01b039283165f81815260056020526040902090939192909116905461140b8160601c90565b906001600160a01b038216156106295763ffffffff16460361143157506107d1926148c7565b5f93508392908390610fc59061147a9061145b906001600160a01b03165b6001600160a01b031690565b946040519283916020830196639277283360e01b885260248401614340565b51925af1611486614358565b506107d157635f0ad7b760e11b5f5260045ffd5b63139f696160e31b5f5260045ffd5b346103ca5760203660031901126103ca57602061ffff6114f663ffffffff6004356114d3816108f7565b1663ffffffff908060031c5f52600c60205260e060405f20549160051b161c1690565b16604051908152f35b346103ca575f3660031901126103ca5760206040515f8152f35b346103ca5760203660031901126103ca57600435611536816103b9565b60018060a01b03165f526005602052608060405f20546040519063ffffffff8116825263ffffffff8160201c16602083015263ffffffff8160401c16604083015260601c6060820152f35b346103ca5760403660031901126103ca577fc40a8c1d6db18d083249778a76a84a78429c4fe53001aba75f470c597afaee2760406004356115c1816108f7565b61ffff6115cc610ba8565b6115d4613a52565b16600c602052631fffffff8260031c165f52825f2060e08360051b168154908382821c1863ffffffff16901b18905563ffffffff8351921682526020820152a1005b346103ca5760603660031901126103ca57611677600435611636816108f7565b60243563ffffffff6044359261164b84610f21565b165f52600860205260405f20905f5260205260405f20906001600160401b03165f5260205260405f2090565b54604051908152602090f35b346103ca5760203660031901126103ca576004356001600160401b0381116103ca576116b3903690600401610472565b906116bc613a52565b6116c58261287a565b906116d36040519283610c6a565b828252602082019260051b8101903682116103ca5780935b8285106116fb576107d184613ec3565b84356001600160401b0381116103ca578201906060823603126103ca576040519161172583610c14565b8035611730816108f7565b835261173e60208201610bb9565b60208401526040810135906001600160401b0382116103ca57019036601f830112156103ca57602092611778849336908581359101612891565b60408201528152019401936116eb565b346103ca5760203660031901126103ca5763ffffffff6004356117aa816108f7565b165f526001602052602060405f2054604051908152f35b346103ca5760603660031901126103ca576004356117de816108f7565b6117e6610ba8565b604435906001600160401b0382116103ca576105fc9261180d610a9f9336906004016106e1565b929091612929565b346103ca5760403660031901126103ca5761183e600435611835816103b9565b602435906129fc565b604080516001600160a01b03939093168352901515602083015290f35b60c03660031901126103ca57600435611873816108f7565b60243590611880826103b9565b6044356001600160401b0381116103ca5761189f903690600401610472565b606492919235906118af826103b9565b608435916118bc836103b9565b6118c46104b8565b906001600160a01b03811615611b1b5763ffffffff85169463ffffffff7f00000000000000000000000000000000000000000000000000000000000076681686148015611b0e575b6110ba578315611aff576001600160a01b0388165f9081526005602052604090209261194a61194561193f865460601c90565b95612578565b613fbd565b15611ace57889291906001600160a01b0385165f5b878110611a5a575050905f6119a06119bb935b888c6040519861199a8a61198c85858d86602086016126bf565b03601f1981018c528b610c6a565b866125c8565b60405180948192632f1c2cd560e21b8352856004840161253f565b0381305afa968715610624577f6a0cf129b799c36943cf19ef7755eafb0b597737ba2f970045385de48107886a97611a3995611a1b945f92611a3e575b50611a0161246b565b3481525f60208201526001600160a01b039093169361403f565b506040516001600160a01b0393841698909316969293849384612cd0565b0390a4005b611a539192503d805f833e6106158183610c6a565b905f6119f8565b909192939450611a6b81888c612cbb565b3590823b156103ca576040516323b872dd60e01b815233600482015230602482015260448101929092525f8260648183875af191821561062457600192611aba575b5001908a9493929161195f565b80610eb35f611ac893610c6a565b5f611aad565b9091906001600160a01b0384163303611af05788925f6119a06119bb93611972565b6348f5c3ed60e01b5f5260045ffd5b630f59b9ff60e01b5f5260045ffd5b5063fffff9be861161190c565b63d721852160e01b5f5260045ffd5b346103ca575f60203660031901126103ca57600435611b48816103b9565b611b50613a52565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031690813b156103ca5760405163ca5eb5e160e01b81526001600160a01b039091166004820152905f908290602490829084905af1801561062457611bbb575080f35b6107d191505f90610c6a565b346103ca5760403660031901126103ca577f69bdfca1ae414a7233840909f9c10a21560d38e0ed4fb50ff50b7b4c29ad96fe600435611c05816103b9565b60243590611c1282611250565b611c1a613a52565b6001600160a01b03165f81815260096020908152604091829020805460ff191660ff9515159586161790558151928352820192909252a1005b346103ca5760203660031901126103ca57600435611c70816108f7565b611c78613a52565b63ffffffff81169063fffff9be821115611cdd576004805463ffffffff60a01b191660a09290921b63ffffffff60a01b169190911790556040519081527fd22acca42bfd0ebef8a1ca8347653f46f782b92b553ba57e0f2294426dfe26ac90602090a1005b633df6e48d60e21b5f5260045ffd5b346103ca5760403660031901126103ca576107d1602435600435611d0f826103b9565b611d286108ed825f526003602052600160405f20015490565b613abe565b346103ca5760a03660031901126103ca57600435611d4a816103b9565b602435611d56816108f7565b60443591611d63836103b9565b60643590611d70826108f7565b60843592611d7d846108f7565b611d85613919565b63ffffffff8116928315610ece5763ffffffff81169586156110ba576001600160a01b038116958615611fbe576001600160a01b038516958615611fbe57627a120063ffffffff831611611faf574603611f735763ffffffff7f00000000000000000000000000000000000000000000000000000000000076681688036110ba57868603611f64575b6001600160a01b0382165f908152600560205260409020611e329061144f90610566565b611f555784611eb6611ec692611ea9611edf96611e8587611e66611f2f9c60018060a01b03165f52600660205260405f2090565b80546001600160a01b0319166001600160a01b03909216919091179055565b611e9c611e9061247a565b63ffffffff909a168a52565b63ffffffff166020890152565b63ffffffff166040870152565b6001600160a01b03166060850152565b6001600160a01b03165f90815260056020526040902090565b8151602080840151604080860151606096870151911b63ffffffff60401b1663ffffffff9094169190921b67ffffffff000000001617919091176001600160601b03199190931b16919091179055565b7f328b68290d8d3a315d25b2476661d7c921ee87029fc767a4916b407e2ee31ede5f80a4005b6341ab882d60e01b5f5260045ffd5b630232505d60e61b5f5260045ffd5b63ffffffff7f0000000000000000000000000000000000000000000000000000000000007668168803611e0e57634d30e69360e11b5f5260045ffd5b634a11e78360e11b5f5260045ffd5b63d92e233d60e01b5f5260045ffd5b346103ca575f3660031901126103ca5760206040517f8970ff45bc1804c7a79662cce9df9b0403588be8e486c6f5a410a2814caa892c8152f35b346103ca5760403660031901126103ca576004356001600160401b0381116103ca576120379036906004016106e1565b602435906001600160401b0382116103ca576105fc9261205e610a9f9336906004016106e1565b929091612d58565b346103ca5760403660031901126103ca576004356001600160401b0381116103ca576120969036906004016106e1565b602435906001600160401b0382116103ca576105fc926120bd610a9f933690600401610472565b929091613044565b346103ca5760403660031901126103ca576107d16004356120e5816108f7565b6024356120f181611250565b6120f9613a52565b15612105573090613a78565b5f90613a78565b346103ca5760203660031901126103ca57600435612129816103b9565b60018060a01b03165f526006602052602060018060a01b0360405f205416604051908152f35b346103ca575f3660031901126103ca57602060ff600b54166040519015158152f35b346103ca5760203660031901126103ca5760043561218e816103b9565b612196613a52565b6001600160a01b031680156121e7575f80546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b5f525f60045260245ffd5b346103ca575f3660031901126103ca576004546040516001600160a01b039091168152602090f35b60a03660031901126103ca5760043561223a816103b9565b6024356001600160401b0381116103ca57612259903690600401610472565b6044356001600160401b0381116103ca57612278903690600401610472565b9360643594612286866103b9565b61228e6104ce565b918415801561241e575b611aff576001600160a01b0381165f908152600560205260409020805460601c95908615610629576122cf6119456122d392612578565b1590565b806123c3575b6123b4576122ea81888588866133a3565b906123295f61230e61230560045463ffffffff9060a01c1690565b97848c88612718565b60405180938192632f1c2cd560e21b83528a6004840161253f565b0381305afa958615610624576105fc9a7fed0c24299d2da4e3728deedbf20de24c4ff0e754c89f20b3d2532fe63b43b531976123a195612372945f92611a3e5750611a0161246b565b5197426123878a5f52600a60205260405f2090565b556040516001600160a01b0390941696939485948561327b565b0390a36040519081529081906020820190565b634a91ec5f60e01b5f5260045ffd5b50604051637347ebb960e01b81526020816004818a5afa908115610624575f916123ef575b50156122d9565b612411915060203d602011612417575b6124098183610c6a565b8101906129d2565b5f6123e8565b503d6123ff565b508115612298565b346103ca5760603660031901126103ca576020612442366106bf565b63ffffffff8135612452816108f7565b165f52600182528160405f205491013560405191148152f35b60405190610cc3604083610c6a565b60405190610cc3608083610c6a565b60405190610cc360e083610c6a565b60405190610cc360c083610c6a565b60405190610cc360a083610c6a565b6001600160401b038111610c2f57601f01601f191660200190565b81601f820112156103ca578051906124e8826124b6565b926124f66040519485610c6a565b828452602083830101116103ca57815f9260208093018386015e8301015290565b906020828203126103ca5781516001600160401b0381116103ca5761253c92016124d1565b90565b60609063ffffffff61253c9493168152600160208201528160408201520190610a5e565b6040513d5f823e3d90fd5b3561253c816108f7565b90604051608081018181106001600160401b03821117610c2f57604052606081935463ffffffff8116835263ffffffff8160201c16602084015263ffffffff8160401c166040840152811c910152565b929150926126069360018060a01b03165f52600560205263ffffffff60406125f1815f20612578565b94828060208801511691161494015116613b66565b9061260f613bce565b91600361ffff61261e856141db565b16036126545761253c9192604051916001600160801b03199060801b1660208301526010825261264f603083610c6a565b614227565b61ffff612660846141db565b633a51740d60e01b5f521660045260245ffd5b81835290916001600160fb1b0383116103ca5760209260051b809284830137010190565b6001600160a01b0390911681525f602082015260606040820181905261253c93910191612673565b6001600160a01b0391821681529116602082015260606040820181905261253c93910191612673565b634e487b7160e01b5f52601160045260245ffd5b63ffffffff1660e0019063ffffffff821161271357565b6126e8565b61276f9293915060018060a01b03165f5260056020526001600160801b0363ffffffff61274760405f20612578565b51164614805f146127be576201adb0905b156127b557816206390e5b81871602160116613b46565b90627a12006001600160801b03831611611faf5763ffffffff166060029063ffffffff8216918203612713576127a761253c926126fc565b906127b0613bce565b613bea565b8161c350612763565b6201b7d890612758565b908060209392818452848401375f828201840152601f01601f1916010190565b61253c94926001600160401b03604060a09463ffffffff813561280a816108f7565b16855260208101356020860152013561282281610f21565b166040830152606082015281608082015201916127c8565b805191908290602001825e015f815290565b91601460209493612873936bffffffffffffffffffffffff199060601b168152019061283a565b9081520190565b6001600160401b038111610c2f5760051b60200190565b92919261289d826124b6565b916128ab6040519384610c6a565b8294818452818301116103ca578281602093845f960137010152565b90606e116103ca57602e0190604090565b906054116103ca5760400190601490565b6129039392610cc39281604051968794602086019061283a565b918237015f815203601f198101845283610c6a565b91602061253c9381815201916127c8565b6129579163ffffffff610d7c9296949596165f52600260205260405f209061ffff165f5260205260405f2090565b8051156129c45783156129be57600284101561298f57505061298b604051928392639a6d49cd60e01b845260048401612918565b0390fd5b90926129a461299f368386612891565b613f85565b806002116103ca57600261253c93019060011901916128e9565b92509050565b50919061253c913691612891565b908160209103126103ca575161253c81611250565b908160209103126103ca575161253c816103b9565b6001600160a01b03165f908152600560205260409020612a2090612578565b612578565b63ffffffff612a36602083015163ffffffff1690565b1615612c9e57612a5e6060612a4f835163ffffffff1690565b9201516001600160a01b031690565b9063ffffffff164603612bc2576040516331a9108f60e11b8152600481018390526020816024816001600160a01b0386165afa5f9181612ba1575b50612aa7575050505f905f90565b6001600160a01b0381163003612ac1575050503090600190565b612b2991602091935b604051637f63c3dd60e01b81526001600160a01b039092166004830152602482015267ffffffffffffffff197f502693d518cccccc945699ac6b0be7c02aef951c921558ec000000000000000016604482015291829081906064820190565b03817f0000000000000000000000000000000000007129af73c46c9f01a3fb4ff61a026001600160a01b03165afa5f9181612b70575b50612b6a5750905f90565b915f9150565b612b9391925060203d602011612b9a575b612b8b8183610c6a565b8101906129e7565b905f612b5f565b503d612b81565b612bbb91925060203d602011612b9a57612b8b8183610c6a565b905f612a99565b6001600160a01b03811680158015612c4d575b15612be4575050505f90600190565b612b29916020918260405180926331a9108f60e11b82528180612c0f8a600483019190602083019252565b03915afa5f9181612c2e575b50612c2857505f93612aca565b93612aca565b612c46919250843d8611612b9a57612b8b8183610c6a565b905f612c1b565b50604051635a2d1e0760e11b815260048101849052602081602481855afa908115610624575f91612c7f575b50612bd5565b612c98915060203d602011612417576124098183610c6a565b5f612c79565b50505f90600190565b634e487b7160e01b5f52603260045260245ffd5b9190811015612ccb5760051b0190565b612ca7565b91602091612ce991959495604085526040850191612673565b6001600160a01b03909416910152565b91908260409103126103ca5760208235612d12816103b9565b92013590565b91908260409103126103ca5760208235612d31816103b9565b92013561253c81611250565b60405190612d4c602083610c6a565b5f808352366020840137565b612d6b612d8892612d73929594956128c7565b810190612cf9565b936001600160a01b0390911692810190612d18565b612ea2578183612dae612a1b61253c9560018060a01b03165f52600560205260405f2090565b91612db883613fbd565b15612e24576001600160a01b03165f908152600760205260409020610fc59250612df291612de59161100e565b546001600160a01b031690565b935b604080516001600160a01b0396871660208201529590931692850192909252606084019190915282906080820190565b505060600151612e3e9061144f906001600160a01b031681565b6040516331a9108f60e11b81526004810185905290602090829060249082905afa5f9181612e81575b50612e775750610fc55f93612df4565b610fc59093612df4565b612e9b91925060203d602011612b9a57612b8b8183610c6a565b905f612e67565b50505061253c612d3d565b356001600160601b0319811692919060148210612ec8575050565b6001600160601b031960149290920360031b82901b16169150565b90612eed8261287a565b612efa6040519182610c6a565b8281528092612f0b601f199161287a565b0190602036910137565b9190811015612ccb5760051b81013590601e19813603018212156103ca5701908135916001600160401b0383116103ca5760200182360381136103ca579190565b908160609103126103ca578035612f6c816103b9565b9160406020830135612d12816103b9565b8051821015612ccb5760209160051b010190565b90602080835192838152019201905f5b818110612fae5750505090565b82516001600160a01b0316845260209384019390920191600101612fa1565b90602080835192838152019201905f5b818110612fea5750505090565b8251845260209384019390920191600101612fdd565b9261302861253c95936130369360018060a01b03168652608060208701526080860190612f91565b908482036040860152612f91565b916060818403910152612fcd565b61306f612a1b611ec661306961306361307d966060969a99989a6128d8565b90612ead565b60601c90565b01516001600160a01b031690565b61308682612ee3565b9161309081612ee3565b9461309a82612ee3565b915f915f5b82811061318357505050815181106130cb5750610fc59061253c93949560405195869460208601613000565b92906130d684612ee3565b936130e081612ee3565b916130ea82612ee3565b935f5b838110613113575050505061253c9394955090610fc59160405195869460208601613000565b8061316761315d613136838e6131588e6131498461314361313660019c8e612f7d565b516001600160a01b031690565b92612f7d565b6001600160a01b039091169052565b612f7d565b6131498389612f7d565b6131718185612f7d565b5161317c8289612f7d565b52016130ed565b61318e818484612f15565b905015613273576131e8816131d58b613149838a6131c56131bb6131b3848d8d612f15565b810190612f56565b9291989093612f7d565b526001600160a01b031692612f7d565b6001600160a01b0316613149838a612f7d565b6131f56131368289612f7d565b61320561144f613136848d612f7d565b6001600160a01b0390911603613220575b6001905b0161309f565b926001809161322f8688612f7d565b5161323a8289612f7d565b5261325561324b613136888c612f7d565b613149838c612f7d565b61326a8b613149836131436131368b85612f7d565b01939050613216565b60019061321a565b949391949290928560408201604083525260608101935f965b8088106132b057505061253c9495506020818503910152612673565b909460208060019263ffffffff89356132c8816108f7565b16815201960197019690613294565b908160011b918083046002149015171561271357565b8181029291811591840414171561271357565b9061330a8261287a565b6133176040519182610c6a565b8281528092613328601f199161287a565b01905f5b82811061333857505050565b60209060405161334781610c34565b5f81525f838201525f60408201525f60608201525f60808201525f60a0820152606060c08201528282850101520161332c565b906001820180921161271357565b906023820180921161271357565b9190820180921161271357565b9391926133b86133b385856132ed565b613300565b935f956001600160401b034216965b85811061343c575050505050509061253c9161342b6133e4612498565b600281529263ffffffff7f00000000000000000000000000000000000000000000000000000000000076681660208501525f60408501526001600160401b03166060840152565b5f60808301523060a083015261413b565b5f5b83811061344e57506001016133c7565b61349261347061346761346284888b612cbb565b61256e565b63ffffffff1690565b63ffffffff908060031c5f52600c60205260e060405f20549160051b161c1690565b63ffffffff8116156110ba57836134a88461337a565b6134b28a856132ed565b6134bb91613396565b61ffff16916134cb84888b612cbb565b6134d49061256e565b906134e085898c612cbb565b6134e99061256e565b6134f290613748565b6001600160a01b031691613507878d8c612cbb565b604051635ed34d0560e11b60208201526001600160a01b0395909516602486015235604480860191909152845261353f606485610c6a565b613547612489565b61ffff909516855263ffffffff1660208501525f60408501526001600160401b038d16606085015261ffff1660808401526001600160a01b031660a083015260c08201528161359686856132ed565b906135a091613396565b906135ab828b612f7d565b526135b69089612f7d565b5060010161343e565b604051906135cc82610c4f565b5f6020838281520152565b91908260409103126103ca576040516135ef81610c4f565b6020808294805184520151910152565b906040828203126103ca5761253c916135d7565b906020909392936040835263ffffffff81511660408401528181015160608401526080613667613651604084015160a08488015260e0870190610a5e565b6060840151868203603f190160a0880152610a5e565b910151151560c08401526001600160a01b03909416910152565b6136e0926040926136906135bf565b5061369a83613748565b6136b16136a56124a7565b63ffffffff9095168552565b60208401528383015260608201525f6080820152815180938192631bb8518b60e31b8352309060048401613613565b03817f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03165afa908115610624575f9161371f575090565b61253c915060403d604011613741575b6137398183610c6a565b8101906135ff565b503d61372f565b63ffffffff16805f52600160205260405f2054908115613766575090565b63f6ff4fb760e01b5f5260045260245ffd5b61c34f1981019190821161271357565b9190820391821161271357565b3561253c81610f21565b6040906001600160401b0361253c94931681528160208201520190610a5e565b939291926137cf600b5460ff1690565b90816138f7575b506138e857610fc56137ff926040519485936304c98a8b60e51b602086015287602486016127e8565b6138128161380c5a613778565b30613cc6565b91901561381e57505050565b63ffffffff7fd191660d5fb7fa40de3038f810fa899670f44a26d29f0609702b778de1c4e5f69160405161385d81610fc560208201944690308761284c565b5190206138e36138d46138ce6138896138758961256e565b63ffffffff165f52600860205260405f2090565b976138a16020820135809a905f5260205260405f2090565b946138c860408301966138b388613795565b6001600160401b03165f5260205260405f2090565b5561256e565b92613795565b9460405193849316958361379f565b0390a3565b6341c8302160e11b5f5260045ffd5b6001600160a01b03165f9081526009602052604081205460ff161591506137d6565b335f9081527f460e1c17541eb4600da639136d22ecdece50dfd5504d40fe2d419370e887d378602052604090205460ff161561395157565b63e2517d3f60e01b5f52336004527f8970ff45bc1804c7a79662cce9df9b0403588be8e486c6f5a410a2814caa892c60245260445ffd5b5f81815260036020908152604080832033845290915290205460ff16156139ac5750565b63e2517d3f60e01b5f523360045260245260445ffd5b5f8181526003602090815260408083206001600160a01b038616845290915290205460ff16613a4c575f8181526003602090815260408083206001600160a01b03861684529091529020805460ff1916600117905533916001600160a01b0316907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b5f546001600160a01b03163303613a6557565b63118cdaa760e01b5f523360045260245ffd5b7f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b9163ffffffff6040921690815f52600160205280835f205582519182526020820152a1565b5f8181526003602090815260408083206001600160a01b038616845290915290205460ff1615613a4c575f8181526003602090815260408083206001600160a01b03861684529091529020805460ff1916905533916001600160a01b0316907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b906001600160801b03809116911601906001600160801b03821161271357565b916001600160801b03613b9e948193948180613bc3575b15613bb957905b15613bb45762031c870181165b16026201adb00116613b46565b90627a12006001600160801b03831611611faf57565b613b91565b5061c35090613b84565b508281161515613b7d565b604051600360f01b60208201526002815261253c602282610c6a565b91600361ffff613bf9856141db565b16036126545760405160809290921b6fffffffffffffffffffffffffffffffff1916602083015260e01b6001600160e01b031916603082015260148152613c41603482610c6a565b600361ffff613c4f846141db565b1603613cba57600161ffff613c6483516148a0565b16019161ffff831161271357610fc561253c926004613c8d95604051968795602087019061283a565b600160f81b815260f09190911b6001600160f01b0319166001820152600560f81b6003820152019061283a565b61ffff612660836141db565b92915f9190829182613cd860046124b6565b96613ce66040519889610c6a565b60048852601f19613cf760046124b6565b013660208a013760208451940192f13d60048111613d1d575b8084525f602085013e9190565b506004613d10565b601f8211613d3257505050565b5f5260205f20906020601f840160051c83019310613d6a575b601f0160051c01905b818110613d5f575050565b5f8155600101613d54565b9091508190613d4b565b91909182516001600160401b038111610c2f57613d9b81613d958454610bc8565b84613d25565b6020601f8211600114613dda578190613dcb9394955f92613dcf575b50508160011b915f199060031b1c19161790565b9055565b015190505f80613db7565b601f19821690613ded845f5260205f2090565b915f5b818110613e2757509583600195969710613e0f575b505050811b019055565b01515f1960f88460031b161c191690555f8080613e05565b9192602060018192868b015181550194019201613df0565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310613e7157505050505090565b9091929394602080613eb4600193603f19868203018752606060408b5163ffffffff815116845261ffff8682015116868501520151918160408201520190610a5e565b97019301930191939290613e62565b5f5b8151811015613f4e5780613ee86040613ee060019486612f7d565b510151613f85565b613f486040613ef78386612f7d565b51015163ffffffff613f098487612f7d565b5151165f526002602052613f4360405f20613f336020613f29878a612f7d565b51015161ffff1690565b61ffff165f5260205260405f2090565b613d74565b01613ec5565b50613f807fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b6749160405191829182613e3f565b0390a1565b600361ffff60028301511603613f985750565b604051639a6d49cd60e01b81526020600482015290819061298b906024830190610a5e565b63ffffffff815116156106295763ffffffff905116461490565b60405190613fe482610c14565b815f81525f60208201526040613ff86135bf565b910152565b906080828203126103ca5761403790604080519361401a85610c14565b80518552602081015161402c81610f21565b6020860152016135d7565b604082015290565b6140a8608094926140c49694614053613fd7565b5060206140608651614693565b95019182518061412c575b5061407585613748565b92511515926140916140856124a7565b63ffffffff9097168752565b602086015260408501526060840152151585830152565b6040518095819482936302637a4560e41b845260048401613613565b03917f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03165af1908115610624575f91614103575090565b61253c915060803d608011614125575b61411d8183610c6a565b810190613ffd565b503d614113565b614135906146b0565b5f61406b565b91909161414881516148a0565b604051600160f01b60208201525f602282015260f09190911b6001600160f01b03191660248201526006815261417f602682610c6a565b915f925b82518410156141ab576141a360019161419c8686612f7d565b5190614e49565b930192614183565b92509290508163ffffffff6141c7602084015163ffffffff1690565b166141d157505090565b61253c92506147b8565b60028151106141eb576002015190565b60405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606490fd5b90600361ffff614236846141db565b1603613cba57600161ffff61424b83516148a0565b16019161ffff831161271357610fc561253c92600461427495604051968795602087019061283a565b600160f81b80825260f09290921b6001600160f01b03191660018201526003810191909152019061283a565b9080601f830112156103ca5781356142b78161287a565b926142c56040519485610c6a565b81845260208085019260051b8201019283116103ca57602001905b8282106142ed5750505090565b81358152602091820191016142e0565b916060838303126103ca578235614313816103b9565b926020810135614322816103b9565b9260408201356001600160401b0381116103ca5761253c92016142a0565b90612ce9602091949394604084526040840190612fcd565b3d15614382573d90614369826124b6565b916143776040519384610c6a565b82523d5f602084013e565b606090565b9080601f830112156103ca57813561439e8161287a565b926143ac6040519485610c6a565b81845260208085019260051b8201019283116103ca57602001905b8282106143d45750505090565b6020809183356143e3816103b9565b8152019101906143c7565b906080828203126103ca578135614404816103b9565b9260208301356001600160401b0381116103ca5782614424918501614387565b9260408101356001600160401b0381116103ca5783614444918301614387565b9260608201356001600160401b0381116103ca5761253c92016142a0565b614471919392938101906143ee565b6001600160a01b039093165f81815260066020526040902091929161449590612de5565b916144b6611945612a1b8560018060a01b03165f52600560205260405f2090565b156144c8575050610cc3939450614aa1565b9150935f5b8451811015614647575f806144e56131368487612f7d565b6144f26131368589612f7d565b906144fd858a612f7d565b51906001600160a01b03811615841461457457506040516340c10f1960e01b602082019081526001600160a01b03909316602482015260448101919091526145488160648101610fc5565b5190828a5af1614556614358565b5015614566576001905b016144cd565b62ec6f7b60e31b5f5260045ffd5b916001600160a01b0381161584146145dc5750604051630852cd8d60e31b6020820190815260248201929092529091506145b18160448101610fc5565b5190828a5af16145bf614358565b50156145cd57600190614560565b631bc5aabf60e21b5f5260045ffd5b6040516323b872dd60e01b602082019081526001600160a01b039485166024830152939091166044820152606481019190915261461c8160848101610fc5565b5190828a5af161462a614358565b501561463857600190614560565b6312171d8360e31b5f5260045ffd5b50949392505050803b156103ca5760405163163b5cc360e31b815260048101929092525f908290602490829084905af1801561062457614685575b50565b80610eb35f610cc393610c6a565b80340361469d5790565b6304fb820960e51b5f523460045260245ffd5b60405163393f876560e21b81527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031690602081600481855afa908115610624575f91614799575b506001600160a01b031691821561478a576040516323b872dd60e01b60208281019182523360248401526001600160a01b03909416604483015260648201929092525f91906147518160848101610fc5565b519082855af115612563575f513d6147815750803b155b61476f5750565b635274afe760e01b5f5260045260245ffd5b60011415614768565b6329b99a9560e11b5f5260045ffd5b6147b2915060203d602011612b9a57612b8b8183610c6a565b5f6146ff565b61253c9060276148149361489160ff8251169163ffffffff60208201511690604081015115156001600160401b036060830151169061ffff6080840151169260a0600180821b0391015116936040519a8b9960208b019061283a565b600160f81b8152600160f01b600182015260f897881b6001600160f81b031916600382015260e09190911b6001600160e01b031916600482015290151590951b600886015260c01b6001600160c01b031916600985015260f01b6001600160f01b031916601184015260601b6001600160601b0319166013830152565b0103601f198101835282610c6a565b61ffff81116148b05761ffff1690565b6306dfcc6560e41b5f52601060045260245260445ffd5b5f5b8351811015614953576001600160a01b0382166148e68286612f7d565b5190803b156103ca576040516323b872dd60e01b81523060048201526001600160a01b038616602482015260448101929092525f908290606490829084905af180156106245761493a575b506001016148c9565b806149465f8093610c6a565b8003126103ca575f614931565b50610cc3929150614ee8565b906149698261287a565b6149766040519182610c6a565b8281528092614987601f199161287a565b01905f5b82811061499757505050565b80606060208093850101520161498b565b6020818303126103ca578051906001600160401b0382116103ca57019080601f830112156103ca5781516149db8161287a565b926149e96040519485610c6a565b81845260208085019260051b820101918383116103ca5760208201905b838210614a1557505050505090565b81516001600160401b0381116103ca57602091614a37878480948801016124d1565b815201910190614a06565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310614a7457505050505090565b9091929394602080614a92600193603f198682030187528951610a5e565b97019301930191939290614a65565b909291614ab6614ab182516132d7565b61495f565b6004545f9390614ace906001600160a01b031661144f565b6001600160a01b03821696908703614d93576c3607fce1ac9e043a86675c5c2f905b5f955b8551871015614cd457614b096131368884612f7d565b9689614b158289612f7d565b5198614b5f60208b614b3e612de58261100e8d60018060a01b03165f52600760205260405f2090565b9460405180809581946331a9108f60e11b8352600483019190602083019252565b03915afa908115610624575f91614cb6575b50306001600160a01b0390911603614ca757611e66600180958c8b8a614c2597858060a01b038116614c2c575b505060405163b18e2bbb60e01b60208201526001600160a01b0380881660248301528c16604482015260648101929092525064ffffffffff6084820152600160a4820152614bef8160c48101610fc5565b614bf9828d612f7d565b52614c04818c612f7d565b506001600160a01b038a165f90815260076020526040902091019b9061100e565b0195614af3565b60405163b18e2bbb60e01b60208201526001600160a01b039182166024820152911660448201526064810183905264ffffffffff60848201525f60a48201529192610fc592614bef92869291614c99918391614c898160c481018a565b614c938383612f7d565b52612f7d565b5001929150508b8a5f614b9e565b6349e27cff60e01b5f5260045ffd5b614cce915060203d8111612b9a57612b8b8183610c6a565b5f614b71565b955050505092935050614ce68161495f565b915f5b828110614d69575050505f614d129160405180938192631592ca1b60e31b835260048301614a42565b0381837f00000000000000000000000000000000000000447e69651d841bd8d104bed4936001600160a01b03165af1801561062457614d4e5750565b614682903d805f833e614d618183610c6a565b8101906149a8565b80614d7660019284612f7d565b51614d818287612f7d565b52614d8c8186612f7d565b5001614ce9565b8190614af0565b614da990600b9593949261283a565b600160f81b815260f093841b6001600160f01b03199081166001830152600160f01b60038301529190931b16600583015260e01b6001600160e01b03191660078201520190565b92614e0461253c97969394601f969361283a565b93151560f81b845260c01b6001600160c01b031916600184015260f01b6001600160f01b031916600983015260601b6001600160601b031916600b820152019061283a565b9061253c90610fc5614e5d825161ffff1690565b91614ea560c0820195614e97614e7c614e77895151613388565b6148a0565b602085015163ffffffff169060405197889460208601614d9a565b03601f198101855284610c6a565b6040810151151594614ec160608301516001600160401b031690565b91614ed660a0612a4f608084015161ffff1690565b91519260405197889660208801614df0565b919091614ef5835161495f565b600454614f0a906001600160a01b031661144f565b6001600160a01b03831603615024576c3607fce1ac9e043a86675c5c2f935b5f5b8151811015614ffe5780614ff8614fe8614f4760019486612f7d565b5189614fb6614f6d612de58461100e8d60018060a01b03165f52600760205260405f2090565b60405163b18e2bbb60e01b60208201526001600160a01b039182166024820152921660448301526064820183905264ffffffffff60848301525f60a48301528160c48101610fc5565b614fc08589612f7d565b52614fcb8488612f7d565b506001600160a01b0388165f90815260076020526040902061100e565b80546001600160a01b0319169055565b01614f2b565b5050604051631592ca1b60e31b81529293505f915082908190614d129060048301614a42565b8193614f2956fea2646970667358221220fee52d7311955066f78324771ae7deefd5385e3abd4f8b126ddc67bfc595206764736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000506aa8bc5da44f9b3329b8c6f7e000000000000000000000000058a766b3210cee94ca150f767d842eb87a8d7ae800000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000447e69651d841bd8d104bed4930000000000000000000000000000000000007129af73c46c9f01a3fb4ff61a02
-----Decoded View---------------
Arg [0] : _endpointLocator (address): 0x000000000000506Aa8Bc5DA44F9b3329b8c6f7E0
Arg [1] : _delegate (address): 0x58A766B3210ceE94Ca150f767D842Eb87A8d7aE8
Arg [2] : _readChannel (uint32): 4294967295
Arg [3] : _delegatexyz (address): 0x00000000000000447e69651d841bD8D104Bed493
Arg [4] : _exclusiveDelegateResolver (address): 0x0000000000007129AF73C46C9F01a3fB4FF61A02
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000506aa8bc5da44f9b3329b8c6f7e0
Arg [1] : 00000000000000000000000058a766b3210cee94ca150f767d842eb87a8d7ae8
Arg [2] : 00000000000000000000000000000000000000000000000000000000ffffffff
Arg [3] : 00000000000000000000000000000000000000447e69651d841bd8d104bed493
Arg [4] : 0000000000000000000000000000000000007129af73c46c9f01a3fb4ff61a02
Deployed Bytecode Sourcemap
1835:44000:41:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;;;;;:::o;:::-;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;;;-1:-1:-1;1835:44000:41;;;7564:104;1835:44000;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;;;;;;;;;;-1:-1:-1;;;2673:47:25;;;:87;;;;1835:44000:41;;;;;;;;;;2673:87:25;-1:-1:-1;;;862:40:37;;-1:-1:-1;2673:87:25;;;1835:44000:41;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;:::o;:::-;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;;;;;;20394:17;1835:44000;;;;;;;20394:40;1835:44000;;;;;;;-1:-1:-1;;;;;1835:44000:41;;20512:37;20508:73;;20611:53;;;20697:136;20611:53;-1:-1:-1;20611:53:41;20754:69;20611:53;;:::i;:::-;1835:44000;;;;;;;;;;;;20754:69;;:::i;:::-;1835:44000;;8277:1;;;;;;;20697:136;;;1835:44000;20697:136;;;:::i;:::-;;:4;;:136;;;;;;;20870:40;20697:136;-1:-1:-1;20697:136:41;;;1835:44000;20870:40;;:::i;:::-;8277:1;;1835:44000;20943:14;;;8277:1;1835:44000;;;;;;;;;;;;;;;;;;;20697:136;;;;;;;-1:-1:-1;20697:136:41;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;:::i;20508:73::-;20558:23;;;-1:-1:-1;20558:23:41;1835:44000;-1:-1:-1;20558:23:41;1835:44000;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;6832:41;1835:44000;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;1835:44000:41;19453:17;1835:44000;;;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;1835:44000:41;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;-1:-1:-1;;4694:10:15;4681:8;-1:-1:-1;;;;;1835:44000:41;4673:31:15;4669:68;;1835:44000:41;;;;;;:::i;:::-;4837:32:15;;;:::i;:::-;4873:14;;;;1835:44000:41;4837:50:15;;;4833:103;;1835:44000:41;;;;;:::i;:::-;;4833:103:15;1835:44000:41;;;;;;:::i;:::-;4896:40:15;;;-1:-1:-1;4896:40:15;1835:44000:41;;;;;;-1:-1:-1;4896:40:15;4669:68;4713:24;;;-1:-1:-1;4713:24:15;4694:10;1835:44000:41;;;-1:-1:-1;4713:24:15;1835:44000:41;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;843:1:16;1835:44000:41;;678:1:15;1835:44000:41;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;-1:-1:-1;1835:44000:41;8027:64;1835:44000;;;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;-1:-1:-1;1835:44000:41;3901:6:25;1835:44000:41;;3901:22:25;1835:44000:41;-1:-1:-1;1835:44000:41;3901:22:25;1835:44000:41;3810:120:25;;1835:44000:41;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;6394:42;1835:44000;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;4330:25:25;1835:44000:41;;;;;;;:::i;:::-;2475:4:25;4300:18;;-1:-1:-1;1835:44000:41;3901:6:25;1835:44000:41;;3901:22:25;1835:44000:41;-1:-1:-1;1835:44000:41;3901:22:25;1835:44000:41;3810:120:25;;4300:18;2475:4;:::i;:::-;4330:25;:::i;1835:44000:41:-;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;1835:44000:41;;;;1819:5:13;1835:44000:41;;;;;:::i;:::-;;;1500:62:27;;;:::i;:::-;1819:5:13;:::i;1835:44000:41:-;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;;;:::i;:::-;735:10:35;-1:-1:-1;;;;;1835:44000:41;;5421:34:25;5417:102;;5529:37;;;:::i;5417:102::-;5478:30;;;-1:-1:-1;5478:30:25;1835:44000:41;-1:-1:-1;5478:30:25;1835:44000:41;;;;;;-1:-1:-1;;1835:44000:41;;;;;;6934:60;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;1835:44000:41;7899:65;1835:44000;;;;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;1835:44000:41;;;;;;;;-1:-1:-1;;1835:44000:41;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;;;;;;;20394:17;1835:44000;;;;;;;;;;;;21748:40;1835:44000;;;21866:37;21862:73;;22058:139;1835:44000;-1:-1:-1;1835:44000:41;22110:77;1835:44000;;;21969:55;;;;;;;;;;;:::i;:::-;;1835:44000;;21969:55;;;;;;:::i;:::-;22110:77;;:::i;1835:44000::-;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;:::o;:::-;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;:::o;:::-;;;;;;-1:-1:-1;1835:44000:41;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;-1:-1:-1;1835:44000:41;;;;;-1:-1:-1;1835:44000:41;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;538:93:22;1835:44000:41;;;;;:::i;:::-;;;;:::i;:::-;;;-1:-1:-1;1835:44000:41;538:93:22;1835:44000:41;;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;538:93:22;1835:44000:41;:::i;:::-;;;;;;-1:-1:-1;;1835:44000:41;;;;;;446:46:13;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;11677:1:41;11660:13;:18;11656:45;;1835:44000;;-1:-1:-1;;;;;1835:44000:41;11711:61;;1835:44000;;;-1:-1:-1;;;;;;1835:44000:41;-1:-1:-1;;;;;1835:44000:41;;;;;6394:42;11875:69;;;;1835:44000;;-1:-1:-1;;;11875:69:41;;-1:-1:-1;;;;;1835:44000:41;;;11875:69;;1835:44000;11677:1;1835:44000;;;;-1:-1:-1;1835:44000:41;;;-1:-1:-1;6394:42:41;11875:69;;;;;;;;1835:44000;-1:-1:-1;;;;;;1835:44000:41;11960:28;-1:-1:-1;;11960:28:41;1835:44000;11875:69;;;-1:-1:-1;11875:69:41;;;:::i;:::-;;;:::i;:::-;;;;11711:61;11749:23;;;-1:-1:-1;11749:23:41;1835:44000;-1:-1:-1;11749:23:41;11656:45;11687:14;;;-1:-1:-1;11687:14:41;1835:44000;-1:-1:-1;11687:14:41;1835:44000;;;;;;-1:-1:-1;;1835:44000:41;;;;;;7045:50;-1:-1:-1;;;;;1835:44000:41;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;:::o;:::-;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;;;;32772:36;8338:10;32772:36;;32768:61;;32908:75;1835:44000;32908:75;1835:44000;;;8277:1;;;;;;1835:44000;32908:75;;;1835:44000;32908:75;;;:::i;:::-;;1835:44000;;32908:75;;;;;;:::i;:::-;1835:44000;;;33025:56;;33067:13;33025:56;33067:13;33025:56;33067:13;33050:4;;33025:56;;:::i;:::-;1835:44000;33015:67;;33097:36;:21;:29;:21;;;1835:44000;;;;33097:13;1835:44000;;;;;;;33097:21;1835:44000;;;;;;;;;;33097:29;1835:44000;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;33097:36;1835:44000;33097:51;33093:84;;33228:43;33235:36;:21;:29;:21;;33477:49;33235:21;1835:44000;;;;33097:13;1835:44000;;;;;;;33235:36;8338:10;33500:9;33050:4;33477:49;:::i;:::-;33541:8;;33537:171;;-1:-1:-1;1835:44000:41;;-1:-1:-1;;;;;1835:44000:41;;;;;;33723:44;;1835:44000;;33723:44;1835:44000;33537:171;33619:79;;;1835:44000;33619:79;;33093:84;33157:20;;;-1:-1:-1;33157:20:41;1835:44000;-1:-1:-1;33157:20:41;32768:61;32817:12;;;-1:-1:-1;32817:12:41;1835:44000;-1:-1:-1;32817:12:41;1835:44000;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;-1:-1:-1;;;;;1835:44000:41;6741:44;1835:44000;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;1500:62:27;;:::i;:::-;1835:44000:41;;;-1:-1:-1;;;;;;1835:44000:41;;;;-1:-1:-1;;;;;1835:44000:41;3052:40:27;1835:44000:41;;3052:40:27;1835:44000:41;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;:::i;:::-;;;;-1:-1:-1;1835:44000:41;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44000:41;;;2217:4:15;2198:24;1835:44000:41;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;17919:87;1835:44000;;;;;:::i;:::-;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;1835:44000:41;;;;;;-1:-1:-1;1835:44000:41;17919:17;1835:44000;;;-1:-1:-1;1835:44000:41;;-1:-1:-1;;;1835:44000:41;;;;;;;-1:-1:-1;;;1835:44000:41;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;1835:44000:41;;;;16698:38;1835:44000;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;1835:44000:41;;;;16646:36;1835:44000;;;;;;16646:36;1835:44000;;;;;;16698:38;1835:44000;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;2954:29:25;1835:44000:41;;;;;;;:::i;:::-;-1:-1:-1;1835:44000:41;2954:6:25;1835:44000:41;;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;;;;;2954:29:25;1835:44000:41;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;16341:4;;;16319:10;:27;16315:59;;1835:44000;8338:10;1835:44000;;;;;:::i;:::-;;33892:44;8338:10;;;6143;33956:38;33974:20;;1835:44000;;33974:14;1835:44000;;;;;;;33974:20;1835:44000;33956:15;:38;:::i;:::-;:54;33952:85;;34118:4;;;:::i;33952:85::-;34019:18;;;-1:-1:-1;34019:18:41;1835:44000;-1:-1:-1;34019:18:41;33888:354;36271:51;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;;;;;;;20394:17;1835:44000;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;36417:34;36413:70;;1835:44000;;36542:13;36510:45;36542:13;;36710:8;;;;:::i;36565:498::-;-1:-1:-1;;;;;36852:32:41;-1:-1:-1;;36908:81:41;;;;36844:41;;-1:-1:-1;;;;;1835:44000:41;36852:32;-1:-1:-1;;;;;1835:44000:41;;;36844:41;1835:44000;;;36908:81;;;;;;;;;;;;;;;;:::i;:::-;36844:159;;;;;;:::i;:::-;;33888:354;37017:35;37038:14;;;-1:-1:-1;37038:14:41;1835:44000;-1:-1:-1;37038:14:41;16315:59;16355:19;;;-1:-1:-1;16355:19:41;1835:44000;-1:-1:-1;16355:19:41;1835:44000;;;;;;-1:-1:-1;;1835:44000:41;;;;;;18693:31;1835:44000;;;;;;:::i;:::-;;;3228:164:0;1835:44000:41;3360:1:0;1835:44000:41;-1:-1:-1;1835:44000:41;18693:22;1835:44000;;8338:10;1835:44000;-1:-1:-1;1835:44000:41;;8338:10;3382:1:0;8338:10:41;;1835:44000;;3228:164:0;;18693:31:41;1835:44000;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;1835:44000:41;7316:83;1835:44000;;;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;17494:44;1835:44000;;;;;;:::i;:::-;;;;:::i;:::-;1500:62:27;;:::i;:::-;1835:44000:41;17432:22;1835:44000;3584:398:0;;;;;;-1:-1:-1;3584:398:0;;-1:-1:-1;3584:398:0;;;;;;;;;;;;;;1835:44000:41;3584:398:0;;;;;;1835:44000:41;;;;;;;;;;;17494:44;1835:44000;;;;;;;-1:-1:-1;;1835:44000:41;;;;7732:86;1835:44000;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;-1:-1:-1;1835:44000:41;7732:86;1835:44000;;;-1:-1:-1;1835:44000:41;;-1:-1:-1;1835:44000:41;;;;-1:-1:-1;1835:44000:41;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;7732:86;1835:44000;;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;1500:62:27;;;:::i;:::-;1835:44000:41;;;:::i;:::-;;8277:1;1835:44000;;8277:1;;;:::i;:::-;1835:44000;;;;;;;;;;;;;;;;;;;;;;;;;1503:37:22;;;:::i;1835:44000:41:-;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;;8277:1;;;;:::i;:::-;1835:44000;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;;:::i;:::-;;-1:-1:-1;1835:44000:41;569:48:13;1835:44000:41;;;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;:::i;:::-;;-1:-1:-1;;;;;1835:44000:41;;14675:25;14671:62;;1835:44000;;;14757:17;1835:44000;14757:17;1835:44000;14747:27;;:67;;;;1835:44000;14743:92;;14849:20;;14845:50;;-1:-1:-1;;;;;1835:44000:41;;;;;;20394:17;1835:44000;;;;;;15070:27;1835:44000;;;;;;;;;;;:::i;:::-;15070:27;:::i;:::-;;;;15141:13;;;;-1:-1:-1;;;;;1835:44000:41;;-1:-1:-1;15156:19:41;;;;;;15108:604;;;-1:-1:-1;15887:77:41;15835:139;15108:604;;1835:44000;;;;15745:56;;;;;;;;1835:44000;15745:56;;;:::i;:::-;;1835:44000;;15745:56;;;;;;:::i;:::-;15887:77;;:::i;:::-;1835:44000;;8277:1;;;;;;;15835:139;;;1835:44000;15835:139;;;:::i;:::-;;:4;;:139;;;;;;;16112:83;15835:139;16112:83;15835:139;15984:112;15835:139;-1:-1:-1;15835:139:41;;;15108:604;1835:44000;;;:::i;:::-;16043:9;1835:44000;;-1:-1:-1;1835:44000:41;16018:51;;1835:44000;-1:-1:-1;;;;;1835:44000:41;;;;15984:112;:::i;:::-;-1:-1:-1;1835:44000:41;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;16112:83;:::i;:::-;;;;1835:44000;15835:139;;;;;;;-1:-1:-1;15835:139:41;;;;;;:::i;:::-;;;;;15177:3;15218:11;;;;;;;;;;;:::i;:::-;1835:44000;15367:81;;;;;;1835:44000;;-1:-1:-1;;;15367:81:41;;15413:10;1835:44000;15367:81;;1835:44000;15433:4;1835:44000;;;;;;;;;;;-1:-1:-1;1835:44000:41;;;-1:-1:-1;15367:81:41;;;;;;;;1835:44000;15367:81;;;15177:3;;1835:44000;15141:13;;;;;;;;15367:81;;;-1:-1:-1;15367:81:41;;;:::i;:::-;;;;15108:604;1835:44000;;;-1:-1:-1;;;;;1835:44000:41;;15640:10;:37;15636:65;;15108:604;;-1:-1:-1;15887:77:41;15835:139;15108:604;;;15636:65;15686:15;;;-1:-1:-1;15686:15:41;1835:44000;-1:-1:-1;15686:15:41;14845:50;14878:17;;;-1:-1:-1;14878:17:41;1835:44000;-1:-1:-1;14878:17:41;14747:67;14778:36;8338:10;14778:36;;14747:67;;14671:62;14709:24;;;-1:-1:-1;14709:24:41;1835:44000;-1:-1:-1;14709:24:41;1835:44000;;;;-1:-1:-1;1835:44000:41;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;3319:8:13;-1:-1:-1;;;;;1835:44000:41;;3319:31:13;;;;;1835:44000:41;;-1:-1:-1;;;3319:31:13;;-1:-1:-1;;;;;1835:44000:41;;;;3319:31:13;;1835:44000:41;;-1:-1:-1;;1835:44000:41;;3319:31:13;;1835:44000:41;;-1:-1:-1;;3319:31:13;;;;;;;;1835:44000:41;;;3319:31:13;;;;-1:-1:-1;3319:31:13;;:::i;1835:44000:41:-;;;;;;-1:-1:-1;;1835:44000:41;;;;17064:37;1835:44000;;;;;:::i;:::-;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;-1:-1:-1;1835:44000:41;;;17012:16;1835:44000;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;;;;;;;;;;;;;;17064:37;1835:44000;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;1835:44000:41;;;18214:43;8338:10;18214:43;;;18210:76;;1835:44000;;;-1:-1:-1;;;;1835:44000:41;;;;;;-1:-1:-1;;;1835:44000:41;;;;;;;;;;;;18339:28;;1835:44000;;18339:28;1835:44000;18210:76;18266:20;;;-1:-1:-1;18266:20:41;1835:44000;-1:-1:-1;18266:20:41;1835:44000;;;;;;-1:-1:-1;;1835:44000:41;;;;4747:26:25;1835:44000:41;;;;;;;:::i;:::-;2475:4:25;4717:18;;-1:-1:-1;1835:44000:41;3901:6:25;1835:44000:41;;3901:22:25;1835:44000:41;-1:-1:-1;1835:44000:41;3901:22:25;1835:44000:41;3810:120:25;;2475:4;4747:26;:::i;1835:44000:41:-;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;2475:4:25;;:::i;:::-;1835:44000:41;;;43377:26;;;43373:53;;1835:44000;;;43440:22;;;43436:47;;-1:-1:-1;;;;;1835:44000:41;;;43497:35;;43493:61;;-1:-1:-1;;;;;1835:44000:41;;;43568:37;;43564:63;;6286:9;1835:44000;;;43641:72;43637:145;;43833:13;43808:38;43833:13;;1835:44000;43909:17;1835:44000;43888:38;;43884:63;;43965:48;;;43961:90;;43856:300;-1:-1:-1;;;;;1835:44000:41;;;;;;20394:17;1835:44000;;;;;44170:68;;:54;;:40;1835:44000;44170:68;44166:110;;11063:38;11178:282;;11063:38;11178:282;11135:40;11063:38;:62;:38;;1835:44000;11063:38;1835:44000;;;;;;;;11063:13;1835:44000;;;;;;;11063:38;1835:44000;;-1:-1:-1;;;;;;1835:44000:41;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;11063:62;11178:282;1835:44000;;:::i;:::-;;;;;;;;11178:282;1835:44000;;;11178:282;;1835:44000;;11178:282;1835:44000;;;11178:282;;1835:44000;;11178:282;-1:-1:-1;;;;;1835:44000:41;;11178:282;;1835:44000;;11178:282;-1:-1:-1;;;;;1835:44000:41;;;;;20394:17;1835:44000;;;;;;;11135:40;1835:44000;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1835:44000:41;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;8338:10:41;;;;;1835:44000;;;;;;;;11476:87;-1:-1:-1;11476:87:41;;1835:44000;44166:110;44247:29;;;-1:-1:-1;44247:29:41;1835:44000;-1:-1:-1;44247:29:41;43961:90;44022:29;;;-1:-1:-1;44022:29:41;1835:44000;-1:-1:-1;44022:29:41;43856:300;1835:44000;44107:17;1835:44000;44086:38;;43856:300;44082:63;32817:12;;;-1:-1:-1;44133:12:41;1835:44000;-1:-1:-1;44133:12:41;43637:145;43736:35;;;-1:-1:-1;43736:35:41;1835:44000;-1:-1:-1;43736:35:41;43564:63;43541:13;;;-1:-1:-1;43614:13:41;1835:44000;-1:-1:-1;43614:13:41;1835:44000;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;6540:38;1835:44000;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;-1:-1:-1;;1835:44000:41;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;-1:-1:-1;;1835:44000:41;;;;488:59:14;1835:44000:41;;;;;:::i;:::-;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;488:59:14;;;528:4;488:59;;:::i;:::-;-1:-1:-1;488:59:14;;:::i;1835:44000:41:-;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;1835:44000:41;19072:13;1835:44000;;;;;;;;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;8131:28;1835:44000;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;2627:22:27;;2623:91;;-1:-1:-1;1835:44000:41;;-1:-1:-1;;;;;;1835:44000:41;;;;;;-1:-1:-1;;;;;1835:44000:41;;3052:40:27;;-1:-1:-1;3052:40:27;1835:44000:41;2623:91:27;2672:31;;;-1:-1:-1;2672:31:27;-1:-1:-1;1835:44000:41;;;-1:-1:-1;2672:31:27;1835:44000:41;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;12762:20;;;:40;;;;1835:44000;12758:70;;-1:-1:-1;;;;;1835:44000:41;;;;;;20394:17;1835:44000;;;;;;;;;;;12991:37;;12987:73;;13076:27;1835:44000;13075:28;1835:44000;;:::i;13076:27::-;13075:28;;1835:44000;13075:28;:88;;;1835:44000;13071:153;;13253:48;;;;;;;:::i;:::-;1835:44000;13335:136;-1:-1:-1;13392:69:41;1835:44000;;;;;;;;;;;13392:69;;;;;:::i;:::-;1835:44000;;8277:1;;;;;;;13335:136;;;1835:44000;13335:136;;;:::i;:::-;;:4;;:136;;;;;;;1835:44000;13335:136;13753:77;13335:136;13753:77;13335:136;13516:135;13335:136;-1:-1:-1;13335:136:41;;;1835:44000;;;:::i;13516:135::-;8277:1;13722:15;;13699:20;;1835:44000;;33974:14;1835:44000;;;;;;;13699:20;1835:44000;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;13753:77;:::i;:::-;;;;1835:44000;;;;;;;;;;;;;13071:153;13186:27;;;-1:-1:-1;13186:27:41;1835:44000;-1:-1:-1;13186:27:41;13075:88;-1:-1:-1;1835:44000:41;;-1:-1:-1;;;13108:55:41;;1835:44000;;;;13108:55;;;;;;;;-1:-1:-1;13108:55:41;;;13075:88;13107:56;;13075:88;;13108:55;;;;1835:44000;13108:55;1835:44000;13108:55;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;12762:40;12786:16;;;12762:40;;1835:44000;;;;;;-1:-1:-1;;1835:44000:41;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;-1:-1:-1;1835:44000:41;2876:5:15;1835:44000:41;;;;-1:-1:-1;1835:44000:41;;2900:13:15;;1835:44000:41;;;2876:37:15;;1835:44000:41;;;8277:1;1835:44000;;8277:1;;1835:44000;8277:1;;:::i;:::-;1835:44000;;8277:1;;1835:44000;8277:1;;:::i;:::-;1835:44000;;8277:1;;;;;:::i;:::-;1835:44000;;8277:1;;38116:560;8277:1;;:::i;:::-;1835:44000;;8277:1;;1835:44000;8277:1;;:::i;:::-;-1:-1:-1;;;;;8277:1:41;;;;1835:44000;;-1:-1:-1;;1835:44000:41;8277:1;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;1835:44000;8277:1;1835:44000;;8277:1;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;8277:1:41;;;;;;;;1835:44000;;;;;8277:1;:::o;:::-;;;;;;;;;;;-1:-1:-1;;;;;8277:1:41;;;;;;;;:::i;:::-;;:::o;:::-;;;1835:44000;8277:1;;;1835:44000;;;;8277:1;;;1835:44000;8277:1;;;;;;;;:::i;:::-;1835:44000;;8277:1;;;;;;;1835:44000;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;28919:653::-;;;;;29308:164;28919:653;1835:44000;;;;;;-1:-1:-1;1835:44000:41;29164:17;1835:44000;;;;;;-1:-1:-1;1835:44000:41;;:::i;:::-;29236:24;;;1835:44000;29236:24;;1835:44000;;;;29236:34;29354:46;;1835:44000;;29308:164;:::i;:::-;29490:27;;;:::i;:::-;1059:20:23;808:1;1835:44000:41;1059:20:23;;;:::i;:::-;1835:44000:41;1059:30:23;1055:82;;2368:74;1835:44000:41;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;3589:22:1;;1835:44000:41;3589:22:1;;;;;;;:::i;:::-;2368:74:23;:::i;1055:82::-;1835:44000:41;1116:20:23;;;:::i;:::-;1098:39;;;-1:-1:-1;1098:39:23;1835:44000:41;1098:39:23;1835:44000:41;;-1:-1:-1;1098:39:23;1835:44000:41;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;;;;;;;;;;:::i;5972:2::-;1835:44000;;;5972:2;;;;;;;;;1835:44000;;;5972:2;;1835:44000;5972:2;;;;:::o;:::-;;:::i;29810:837::-;45678:40;29810:837;;;;1835:44000;;;;;;-1:-1:-1;1835:44000:41;30030:17;1835:44000;;-1:-1:-1;;;;;1835:44000:41;;;-1:-1:-1;1835:44000:41;;:::i;:::-;;;30128:13;30096:45;44646:182;;;;;5634:6;44646:182;;44898:75;;;;6091:5;44898:75;1835:44000;;;6091:5;1835:44000;5529:7;1835:44000;45678:40;:::i;:::-;1835:44000;6286:9;-1:-1:-1;;;;;1835:44000:41;;45733:49;45729:97;;1835:44000;;5972:2;;1835:44000;;;;5972:2;;;;;30387:89;3994:12:23;30387:89:41;;:::i;:::-;30522:27;;;:::i;:::-;3994:12:23;:::i;44898:75:41:-;;5743:6;44898:75;;44646:182;5529:7;44646:182;;;8338:10;;;1835:44000;8338:10;;1835:44000;;;;;;8338:10;-1:-1:-1;8338:10:41;;;;;;1835:44000;;-1:-1:-1;;1835:44000:41;8338:10;;;:::o;:::-;;;;-1:-1:-1;;;;;8338:10:41;;;1835:44000;;;;;;:::i;:::-;;;;8338:10;;;1835:44000;8338:10;;;1835:44000;8338:10;1835:44000;;;;:::i;:::-;;8338:10;;;1835:44000;8338:10;;;1835:44000;8338:10;;;;;;;;:::i;:::-;1835:44000;;;8338:10;1835:44000;;8338:10;;;1835:44000;;;;;8338:10;:::o;:::-;;;;;;;;1835:44000;8338:10;;;;;;;;;;:::i;:::-;1835:44000;;;8338:10;;:::o;1835:44000::-;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;8277:1;1835:44000;;8277:1;;;:::i;:::-;1835:44000;;;;;;;;;;;;;;;;-1:-1:-1;1835:44000:41;;8338:10;;;;1835:44000::o;:::-;;25336:3;1835:44000;;;25333:2;1835:44000;;;;:::o;:::-;;26695:2;1835:44000;;;26692:2;1835:44000;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;8338:10;;;;-1:-1:-1;8338:10:41;;1835:44000;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;3510:981:22:-;1835:44000:41;3510:981:22;1835:44000:41;3701:31:22;3510:981;;;;;1835:44000:41;-1:-1:-1;1835:44000:41;3701:15:22;1835:44000:41;;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;;;;3861:20:22;3857:46;;3964:25;;3960:46;;3701:15;4129:25;;;4125:267;;1835:44000:41;;4455:29:22;1835:44000:41;;4455:29:22;;;;;;;;;;;;:::i;:::-;;;;4125:267;1835:44000:41;;4170:34:22;1835:44000:41;;;;;:::i;:::-;4170:34:22;:::i;:::-;1835:44000:41;3701:15:22;1835:44000:41;;;3701:15:22;4340:41;1835:44000:41;;;;;;4340:41:22;;:::i;3960:46::-;3991:15;-1:-1:-1;3991:15:22;-1:-1:-1;3991:15:22:o;3857:46::-;1835:44000:41;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;22770:2054::-;-1:-1:-1;;;;;1835:44000:41;;;;;20394:17;1835:44000;;;;;;;;:::i;22984:40::-;1835:44000;:::i;:::-;;;23039:24;;;1835:44000;;;;;;;23039:29;23035:60;;1835:44000;23211:20;1835:44000;;;;;;;;23211:20;;1835:44000;-1:-1:-1;;;;;1835:44000:41;;;;23241:18;1835:44000;;23154:13;23122:45;23154:13;;1835:44000;;-1:-1:-1;;;23302:49:41;;;;;1835:44000;;;23039:24;1835:44000;;;-1:-1:-1;;;;;1835:44000:41;;23302:49;;-1:-1:-1;;23302:49:41;;;23270:1145;-1:-1:-1;23298:460:41;;23717:26;;;-1:-1:-1;23717:26:41;-1:-1:-1;23717:26:41;:::o;23298:460::-;-1:-1:-1;;;;;1835:44000:41;;23415:4;23398:22;23415:4;;;;;;23444:28;23467:4;23444:28;:::o;23394:162::-;24526:163;23519:18;23039:24;23519:18;23394:162;23270:1145;1835:44000;;-1:-1:-1;;;24526:163:41;;-1:-1:-1;;;;;1835:44000:41;;;24526:163;;;1835:44000;;;;;-1:-1:-1;;24660:19:41;1835:44000;;;;;;;;;;;;;;;24526:163;;1835:44000;24553:35;-1:-1:-1;;;;;1835:44000:41;24526:163;;-1:-1:-1;;24526:163:41;;;23270:1145;-1:-1:-1;24522:296:41;;24781:26;;-1:-1:-1;24781:26:41;:::o;24522:296::-;24728:21;-1:-1:-1;;;24728:21:41:o;24526:163::-;;;;;23039:24;24526:163;23039:24;24526:163;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;23302:49;;;;;23039:24;23302:49;23039:24;23302:49;;;;;;;:::i;:::-;;;;;23270:1145;-1:-1:-1;;;;;1835:44000:41;;23908:37;;:92;;;;23270:1145;23904:501;;;24020:25;;;-1:-1:-1;24020:25:41;24040:4;24020:25;:::o;23904:501::-;24526:163;1835:44000;23039:24;1835:44000;;;;8277:1;;;;;24088:52;;;;;;;;;1835:44000;;;;;;;;24088:52;;;;;-1:-1:-1;;24088:52:41;;;23904:501;-1:-1:-1;24084:307:41;;24349:23;-1:-1:-1;24084:307:41;23270:1145;;24084:307;;23270:1145;;24088:52;;;;;;;;;;;;;;;:::i;:::-;;;;;23908:92;-1:-1:-1;1835:44000:41;;-1:-1:-1;;;23949:51:41;;;;;1835:44000;;;23039:24;1835:44000;;;23949:51;;;;;;;;-1:-1:-1;23949:51:41;;;23908:92;;;;23949:51;;;;23039:24;23949:51;23039:24;23949:51;;;;;;;:::i;:::-;;;;23035:60;23070:25;;-1:-1:-1;23070:25:41;23090:4;23070:25;:::o;1835:44000::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;8277:1;;1835:44000;8277:1;:::i;:::-;-1:-1:-1;1835:44000:41;;;;8277:1;1835:44000;;;:::o;25144:1066::-;25324:16;25436:38;25144:1066;25313:48;25144:1066;;;;25324:16;:::i;:::-;25313:48;;;;:::i;:::-;1835:44000;-1:-1:-1;;;;;1835:44000:41;;;;25436:38;;;;:::i;:::-;25485:33;;25562:36;;1835:44000;25562:36;26162:41;25562:36;1835:44000;;;;;;;;20394:17;1835:44000;;;;;;;;25613:27;;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44000:41;;;;;25737:15;1835:44000;;;;;26162:41;;-1:-1:-1;25737:43:41;;;;:34;1835:44000;25737:43;1835:44000;-1:-1:-1;;;;;1835:44000:41;;;25737:43;25609:536;;1835:44000;;;-1:-1:-1;;;;;1835:44000:41;;;26162:41;;;1835:44000;;;;;;;;;;;;;;;;;;;;;;;;;;25609:536;-1:-1:-1;;1835:44000:41;25895:20;1835:44000;25884:40;;:32;;-1:-1:-1;;;;;1835:44000:41;25884:32;1835:44000;25884:40;1835:44000;;-1:-1:-1;;;25884:49:41;;;;;1835:44000;;;;25884:49;;1835:44000;;;;;;25884:49;;-1:-1:-1;;25884:49:41;;;25609:536;-1:-1:-1;25880:255:41;;26097:23;26162:41;-1:-1:-1;25880:255:41;25609:536;;25880:255;26162:41;25976:18;25880:255;25609:536;;25884:49;;;;;;;;;;;;;;;:::i;:::-;;;;;25485:33;25506:12;;;;;:::i;1835:44000::-;;-1:-1:-1;;;;;;1835:44000:41;;;;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;;1835:44000:41;;;;;;;8338:10;;;1835:44000;;;-1:-1:-1;1835:44000:41:o;:::-;;;;;:::i;:::-;8277:1;1835:44000;;8277:1;;;:::i;:::-;1835:44000;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;8338:10;;1835:44000;-1:-1:-1;1835:44000:41;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;;;;;;;;;;;;;8338:10;;1835:44000;-1:-1:-1;1835:44000:41;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;26475:2072::-;1835:44000;26743:36;26667:33;26675:24;26683:15;1835:44000;26475:2072;1835:44000;26475:2072;;;;;26683:15;:::i;:::-;26675:24;;:::i;:::-;1835:44000;;;;;26814:20;1835:44000;-1:-1:-1;;;;;1835:44000:41;;;;26876:32;;;:::i;:::-;26947;;;;:::i;:::-;27017;;;;:::i;:::-;27060:23;-1:-1:-1;27098:13:41;-1:-1:-1;27113:21:41;;;;;;1835:44000;;;;;27862:29;;27858:606;;1835:44000;28481:59;1835:44000;28481:59;1835:44000;;;26692:2;1835:44000;28481:59;;;;;;;:::i;27858:606::-;27945:26;;;;;:::i;:::-;28021;;;;:::i;:::-;28096;;;;:::i;:::-;28142:13;-1:-1:-1;28157:15:41;;;;;;1835:44000;;;;28373:80;1835:44000;;;;;28373:80;1835:44000;26692:2;1835:44000;28373:80;;;;;;;:::i;28174:3::-;28221:14;28253:34;28275:12;;28221:14;;28197:38;28221:14;28197:38;28221:14;;;1835:44000;28221:14;;;:::i;:::-;1835:44000;-1:-1:-1;;;;;1835:44000:41;;;28221:14;28197:38;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;;;;;;28197:38;28275:12;:::i;:::-;28253:34;;;;:::i;:::-;28326:11;;;;:::i;:::-;8277:1;28305:32;;;;:::i;:::-;1835:44000;;28142:13;;27136:3;27159:13;;;;;:::i;:::-;:25;;;27155:152;;27321:100;27378:13;27321:100;27378:13;27321:100;27378:13;;27321:100;27367:54;27378:13;;;;;:::i;:::-;27367:54;;;;:::i;:::-;27321:100;;;;;;:::i;:::-;1835:44000;-1:-1:-1;;;;;1835:44000:41;;27321:100;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;27321:100;;;;:::i;:::-;27440:14;;;;;:::i;:::-;:30;27458:12;;;;;:::i;27440:30::-;-1:-1:-1;;;;;1835:44000:41;;;27440:30;27436:300;;27136:3;1835:44000;27136:3;27098:13;1835:44000;27098:13;;27436:300;27514:11;1835:44000;27514:11;;;;;;:::i;:::-;8277:1;27490:35;;;;:::i;:::-;1835:44000;27543:41;27570:14;;;;;:::i;:::-;27543:41;;;;:::i;:::-;27602:37;27627:12;27602:37;27627:12;;;;;;:::i;27602:37::-;1835:44000;27436:300;;;;;27155:152;1835:44000;27284:8;;;1835:44000;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;39400:1;1835:44000;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;8277:1;1835:44000;;8277:1;;;:::i;:::-;1835:44000;;;;;;;;;;:::i;:::-;;;-1:-1:-1;1835:44000:41;;;;;;;;;:::o;:::-;;;;;8277:1;;;:::i;:::-;-1:-1:-1;1835:44000:41;;-1:-1:-1;1835:44000:41;;;;-1:-1:-1;1835:44000:41;;;;-1:-1:-1;1835:44000:41;;;;-1:-1:-1;1835:44000:41;;;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;;;;;;;;38183:1;1835:44000;;;;;;;:::o;:::-;;7847:2:24;1835:44000:41;;;;;;;:::o;:::-;;;;;;;;;;:::o;37418:1526::-;;;;37758:53;37781:29;;;;:::i;:::-;37758:53;:::i;:::-;37827:13;37839:1;38336:15;-1:-1:-1;;;;;38336:15:41;1835:44000;37822:879;37842:19;;;;;;8234:1;;;;;;;38885:52;8234:1;38765:102;8234:1;;:::i;:::-;1835:44000;8234:1;;38765:102;1835:44000;38799:17;1835:44000;38505:152;38765:102;;1835:44000;;;38765:102;;1835:44000;-1:-1:-1;;;;;1835:44000:41;38116:560;38765:102;;1835:44000;;38765:102;1835:44000;38116:560;38765:102;;1835:44000;38861:4;38116:560;38765:102;;1835:44000;38885:52;:::i;37863:3::-;37839:1;37902:15;;;;;;37863:3;38183:1;1835:44000;37827:13;;37919:3;37965:35;;37992:7;;;;;;:::i;:::-;;:::i;:::-;1835:44000;;;;37965:35;1835:44000;3228:164:0;1835:44000:41;3360:1:0;1835:44000:41;-1:-1:-1;1835:44000:41;18693:22;1835:44000;;8338:10;1835:44000;-1:-1:-1;1835:44000:41;;8338:10;3382:1:0;8338:10:41;;1835:44000;;3228:164:0;;37965:35:41;1835:44000;;;38022:18;38018:43;;38179:5;;;;:::i;:::-;38187:19;;;;:::i;:::-;38179:27;;;:::i;:::-;1835:44000;;38240:7;;;;;;:::i;:::-;;;;:::i;:::-;38453;;;;;;:::i;:::-;;;;:::i;:::-;38436:25;;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;38624:11;;;;;;:::i;:::-;1835:44000;;-1:-1:-1;;;38505:152:41;;;;-1:-1:-1;;;;;1835:44000:41;;;;38505:152;;;1835:44000;;;;;;;;;;38505:152;;;1835:44000;;38505:152;:::i;:::-;1835:44000;;:::i;:::-;;;;;;;;;38505:152;38116:560;;1835:44000;;;38116:560;;1835:44000;-1:-1:-1;;;;;1835:44000:41;;38116:560;;;1835:44000;;;38116:560;;;1835:44000;-1:-1:-1;;;;;1835:44000:41;38116:560;;;1835:44000;38116:560;;;1835:44000;38093:15;;;;;:::i;:::-;:19;;;;:::i;:::-;38080:596;;;;;:::i;:::-;;;;;;:::i;:::-;;38183:1;1835:44000;37887:13;;1835:44000;;;8277:1;;;;:::i;:::-;-1:-1:-1;1835:44000:41;;;;;;;:::o;:::-;;;;;;;;;;;;8277:1;;;:::i;:::-;1835:44000;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;:::o;2038:391:16:-;2259:163;2038:391;2291:86;2038:391;1835:44000:41;;:::i;:::-;;2316:25:16;;;:::i;:::-;2291:86;1835:44000:41;;:::i;:::-;;;;;;;;2291:86:16;;;;1835:44000:41;2291:86:16;;;1835:44000:41;2291:86:16;;;1835:44000:41;-1:-1:-1;2291:86:16;;;1835:44000:41;;;8277:1;;;;;;;2259:163:16;;2403:4;2259:163;;;;;:::i;:::-;;1835:44000:41;2259:8:16;-1:-1:-1;;;;;1835:44000:41;2259:163:16;;;;;;;-1:-1:-1;2259:163:16;;;2240:182;2038:391;:::o;2259:163::-;;;;2291:86;2259:163;2291:86;2259:163;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;2718:196:13;1835:44000:41;;;-1:-1:-1;1835:44000:41;2822:5:13;1835:44000:41;;;-1:-1:-1;1835:44000:41;;2847:18:13;;;2843:43;;2896:11;2718:196;:::o;2843:43::-;2874:12;;;-1:-1:-1;2874:12:13;;1835:44000:41;;-1:-1:-1;2874:12:13;5417:6:41;-1:-1:-1;;5417:6:41;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;-1:-1:-1;;;;;5417:6:41;;;1835:44000;;;5417:6;;;;;;;;:::i;30929:1103::-;;;;;1835:44000;31142:16;1835:44000;;;;;;31142:47;;;;30929:1103;31138:82;;;31297:77;;1835:44000;;;8277:1;;;;;;31297:77;;;;;;;;;:::i;:::-;31620:51;31468:9;:29;:9;:29;:::i;:::-;31628:4;31620:51;:::i;:::-;31686:8;;;31682:344;;30929:1103;;;:::o;31682:344::-;1835:44000;31947:68;1835:44000;;;31783:56;;;31297:77;31783:56;;31825:13;;31628:4;;31783:56;;:::i;:::-;1835:44000;31773:67;;31947:68;31993:13;31961:14;31854:29;31868:14;;;:::i;:::-;1835:44000;;;;33097:13;1835:44000;;;;;;;31854:29;31884:14;31854:45;31297:77;31884:14;;1835:44000;31854:45;;1835:44000;;;;;;;;;;31854:45;31900:13;31854:60;1835:44000;31900:13;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;31854:60;1835:44000;31961:14;:::i;:::-;31993:13;;:::i;:::-;1835:44000;;;;;;;31947:68;;;:::i;:::-;;;;30929:1103::o;31138:82::-;31198:22;;;;;;;;31142:47;-1:-1:-1;;;;;1835:44000:41;;;;;31163:16;1835:44000;;;;;;;;13075:28;;-1:-1:-1;31142:47:41;;3199:103:25;735:10:35;-1:-1:-1;1835:44000:41;;;;;;;;;;;;3519:23:25;3515:108;;3199:103::o;3515:108::-;3565:47;;;-1:-1:-1;3565:47:25;735:10:35;3565:47:25;1835:44000:41;6540:38;1835:44000;;;-1:-1:-1;3565:47:25;3199:103;-1:-1:-1;1835:44000:41;;;2954:6:25;1835:44000:41;;;;;;;;735:10:35;1835:44000:41;;;;;;;;;;3519:23:25;3515:108;;3199:103;:::o;3515:108::-;3565:47;;;-1:-1:-1;3565:47:25;735:10:35;3565:47:25;1835:44000:41;;;;-1:-1:-1;3565:47:25;6179:316;1835:44000:41;;;;2954:6:25;1835:44000:41;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;;;;2954:6:25;1835:44000:41;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;-1:-1:-1;;1835:44000:41;6347:4:25;1835:44000:41;;;735:10:35;;-1:-1:-1;;;;;1835:44000:41;;6370:40:25;-1:-1:-1;;6370:40:25;6347:4;6424:11;:::o;6272:217::-;6466:12;;1835:44000:41;6466:12:25;:::o;1796:162:27:-;1710:6;1835:44000:41;-1:-1:-1;;;;;1835:44000:41;735:10:35;1855:23:27;1851:101;;1796:162::o;1851:101::-;1901:40;;;1710:6;1901:40;735:10:35;1901:40:27;1835:44000:41;;1710:6:27;1901:40;2286:134:13;2393:20;2286:134;1835:44000:41;;2286:134:13;1835:44000:41;;;-1:-1:-1;1835:44000:41;2359:5:13;1835:44000:41;;;;-1:-1:-1;1835:44000:41;;;;2393:20:13;1835:44000:41;;;;;;2393:20:13;2286:134::o;6730:317:25:-;1835:44000:41;;;;2954:6:25;1835:44000:41;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;;;;;;2954:6:25;1835:44000:41;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;735:10:35;;-1:-1:-1;;;;;1835:44000:41;;6922:40:25;-1:-1:-1;;6922:40:25;1835:44000:41;6976:11:25;:::o;6091:5:41:-;;-1:-1:-1;;;;;6091:5:41;;1835:44000;;;6091:5;;-1:-1:-1;;;;;6091:5:41;;;;:::o;44289:1544::-;;-1:-1:-1;;;;;45678:40:41;44289:1544;;;;45181:56;;;;44289:1544;45181:175;;;;;45416:84;;;5529:7;;1835:44000;;45416:84;1835:44000;5634:6;;;1835:44000;45678:40;:::i;:::-;1835:44000;6286:9;-1:-1:-1;;;;;1835:44000:41;;45733:49;45729:97;;44289:1544::o;45416:84::-;;;45181:175;;5743:6;45181:175;;;:56;1835:44000;;;;45193:44;;45181:56;;1294:107:23;1835:44000:41;;-1:-1:-1;;;1370:24:23;;;808:1;1370:24;;;;;1835:44000:41;1370:24:23;:::i;1003:152::-;;808:1;1835:44000:41;1059:20:23;;;:::i;:::-;1835:44000:41;1059:30:23;1055:82;;1835:44000:41;;;;;;;-1:-1:-1;;1835:44000:41;4234:37:1;;;1835:44000:41;;8277:1;-1:-1:-1;;;;;;8277:1:41;1835:44000;;;;;4234:37:1;;;;1835:44000:41;4234:37:1;:::i;:::-;808:1:23;1835:44000:41;1059:20:23;;;:::i;:::-;1835:44000:41;1059:30:23;1055:82;;306:1:1;1835:44000:41;6912:25:23;1835:44000:41;;6912:25:23;:::i;:::-;1835:44000:41;250:1:1;;1835:44000:41;250:1:1;;;;;6809:221:23;1835:44000:41;250:1:1;;1835:44000:41;;;6809:221:23;;;;;;250:1:1;;:::i;:::-;-1:-1:-1;;;250:1:1;;808::23;;;;;-1:-1:-1;;;;;;808:1:23;1835:44000:41;250:1:1;;808::23;-1:-1:-1;;;808:1:23;250::1;;;;;;:::i;1055:82:23:-;1835:44000:41;1116:20:23;;;:::i;745:1292:47:-;;;33228:43:41;745:1292:47;;;;1835:44000:41;;;;:::i;:::-;;8277:1;1835:44000;;8277:1;;;:::i;:::-;1835:44000;;;;;;;;:::i;:::-;;;;;;;1269:722:47;;;;;;;;1835:44000:41;1269:722:47;;;;745:1292;1269:722;;;33228:43:41;1269:722:47;;;;2000:30;745:1292;:::o;1269:722::-;;1835:44000:41;1269:722:47;;1835:44000:41;;;;;;;;;:::o;:::-;-1:-1:-1;1835:44000:41;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;-1:-1:-1;8338:10:41;;1835:44000;;;;;;;-1:-1:-1;1835:44000:41;;;;;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;-1:-1:-1;1835:44000:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8338:10;;1835:44000;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2237:514:22;2357:1;2389:3;1835:44000:41;;2360:27:22;;;;;2542:19;:27;;:19;1835:44000:41;2542:19:22;;;:::i;:::-;;:27;;;:::i;:::-;1835:44000:41;2542:27:22;2656:19;;;;:::i;:::-;;:27;;1835:44000:41;2600:19:22;;;;:::i;:::-;;1835:44000:41;;2357:1:22;1835:44000:41;2584:15:22;1835:44000:41;;2584:69:22;2542:27;2357:1;1835:44000:41;2625:27:22;1835:44000:41;2625:19:22;;;;:::i;:::-;;:27;1835:44000:41;;;;;2625:27:22;1835:44000:41;;;;;;;;;;;2584:69:22;1835:44000:41;:::i;:::-;;2345:13:22;;2360:27;;2709:35;;2360:27;2542;1835:44000:41;2709:35:22;;;;;:::i;:::-;;;;2237:514::o;4631:264::-;808:1:23;1835:44000:41;4743:71:22;;;;1835:44000:41;4827:28:22;4823:65;;4631:264;:::o;4823:65::-;1835:44000:41;;-1:-1:-1;;;4864:24:22;;1835:44000:41;4864:24:22;;;1835:44000:41;;;;;;;;;;;:::i;42846:239::-;1835:44000;;;;42950:33;42946:69;;1835:44000;;;;43065:13;43033:45;42846:239;:::o;1835:44000::-;;;8277:1;;;;:::i;:::-;1835:44000;-1:-1:-1;1835:44000:41;;-1:-1:-1;1835:44000:41;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;8277:1;;;;:::i;:::-;1835:44000;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::o;3188:766:16:-;3809:92;;3188:766;;3755:192;3188:766;;1835:44000:41;;:::i;:::-;;3617:15:16;3577:26;8277:1:41;;3577:26:16;:::i;:::-;3617:15;;8277:1:41;;;3617:19:16;3613:53;;3188:766;3834:25;;;;:::i;:::-;8277:1:41;;3881:19:16;;1835:44000:41;3809:92:16;1835:44000:41;;:::i;:::-;;;;;;;;3809:92:16;3617:15;3809:92;;1835:44000:41;3809:92:16;;;1835:44000:41;3809:92:16;;;1835:44000:41;;;3809:92:16;;;1835:44000:41;;3809:92:16;;1835:44000:41;8277:1;;;;;;;;;3755:192:16;;;;;;:::i;:::-;;;:8;-1:-1:-1;;;;;1835:44000:41;3755:192:16;;;;;;;-1:-1:-1;3755:192:16;;;3677:270;3188:766;:::o;3755:192::-;;;;3809:92;3755:192;3809:92;3755:192;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;3613:53;3650:15;;;:::i;:::-;3613:53;;;6561:451:24;;;;7231:34;1835:44000:41;;7231:34:24;:::i;:::-;1835:44000:41;;-1:-1:-1;;;7187:79:24;;;808:1:23;1835:44000:41;1467:1:24;;;808::23;;;;;;-1:-1:-1;;;;;;808:1:23;1467::24;;;808::23;7187:79:24;;;;;1835:44000:41;7187:79:24;:::i;:::-;7281:13;1835:44000:41;7276:133:24;7325:3;1835:44000:41;;7296:27:24;;;;;7350:48;8277:1:41;7378:19:24;;;;;:::i;:::-;;7350:48;;:::i;:::-;7325:3;1835:44000:41;7281:13:24;;;7296:27;;;;;;6760:57;1835:44000:41;;7187:79:24;6831:25;;1835:44000:41;;;;;;;6827:159:24;;6995:10;;6561:451;:::o;6827:159::-;6931:44;;;;:::i;12935:305:40:-;13065:1;1835:44000:41;;13039:27:40;1835:44000:41;;13065:1:40;13127:81;;12935:305;:::o;1835:44000:41:-;;;-1:-1:-1;;;1835:44000:41;;;;;;;;;;;;-1:-1:-1;;;1835:44000:41;;;;;;;6602:435:23;;808:1;1835:44000:41;1059:20:23;;;:::i;:::-;1835:44000:41;1059:30:23;1055:82;;1835:44000:41;;6912:25:23;1835:44000:41;;6912:25:23;:::i;:::-;1835:44000:41;250:1:1;;1835:44000:41;250:1:1;;;;;6809:221:23;1835:44000:41;250:1:1;;1835:44000:41;;;6809:221:23;;;;;;250:1:1;;:::i;:::-;-1:-1:-1;;;250:1:1;;;808::23;;;;;-1:-1:-1;;;;;;808:1:23;1835:44000:41;250:1:1;;808::23;;250::1;;;;;;;;;:::i;1835:44000:41:-;;;;;;;;;;;;;;;:::i;:::-;;8277:1;1835:44000;;8277:1;;;:::i;:::-;1835:44000;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;8277:1;1835:44000;;8277:1;;;:::i;:::-;1835:44000;;;-1:-1:-1;1835:44000:41;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;8277:1;1835:44000;;8277:1;;;:::i;:::-;1835:44000;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1835:44000:41;;;;;;;;:::i;34254:1851::-;34461:64;34254:1851;;;;34461:64;;;;:::i;:::-;-1:-1:-1;;;;;1835:44000:41;;;;;;;11063:13;1835:44000;;;;;;;;34568:28;;;1835:44000;34568:28;34640:40;34706:27;1835:44000;34640:40;;1835:44000;;;;;;;;20394:17;1835:44000;;;;;;;34706:27;34640:40;;;35011:8;;;;;;;:::i;34860:1239::-;35056:13;;;-1:-1:-1;35092:3:41;1835:44000;;35071:19;;;;;-1:-1:-1;35136:14:41;;;;;;:::i;:::-;35187:12;;;;;:::i;:::-;35235:11;;;;;:::i;:::-;8277:1;;-1:-1:-1;;;;;1835:44000:41;;35269:24;1835:44000;;;;-1:-1:-1;1835:44000:41;;-1:-1:-1;;;35381:67:41;;;;;;-1:-1:-1;;;;;1835:44000:41;;;35381:67;;;1835:44000;;;;;;;;35381:67;1835:44000;;;;35381:67;1835:44000;35381:67;35359:90;;;;;;;;:::i;:::-;;35475:8;35471:33;;1835:44000;35265:766;;1835:44000;35056:13;;35471:33;35492:12;;;-1:-1:-1;35492:12:41;35381:67;-1:-1:-1;35492:12:41;35265:766;1835:44000;-1:-1:-1;;;;;1835:44000:41;;35533:22;1835:44000;;;;-1:-1:-1;1835:44000:41;;-1:-1:-1;;;35619:49:41;;;;;;;;;1835:44000;;;;35619:49;;-1:-1:-1;35619:49:41;1835:44000;;;;35619:49;1835:44000;35619:49;35597:72;;;;;;;;:::i;:::-;;35695:8;35691:33;;1835:44000;35529:502;35265:766;;35691:33;35712:12;;;-1:-1:-1;35712:12:41;35619:49;-1:-1:-1;35712:12:41;35529:502;1835:44000;;-1:-1:-1;;;35836:95:41;;;;;;-1:-1:-1;;;;;1835:44000:41;;;35836:95;;;1835:44000;;;;;;;;;;;;;;;;35836:95;1835:44000;;;;35836:95;1835:44000;35836:95;35789:164;;;;;;;;:::i;:::-;;35979:8;35975:37;;1835:44000;35529:502;35265:766;;35975:37;35996:16;;;-1:-1:-1;35996:16:41;35836:95;-1:-1:-1;35996:16:41;35071:19;;;;;;;;36059:29;;;;;1835:44000;;-1:-1:-1;;;36059:29:41;;;;;1835:44000;;;;-1:-1:-1;;1835:44000:41;;;;;;-1:-1:-1;;36059:29:41;;;;;;;;35051:994;34860:1239;34254:1851::o;36059:29::-;;;-1:-1:-1;36059:29:41;;;:::i;4650:191:16:-;4749:9;;:23;4745:62;;4650:191;:::o;4745:62::-;4781:26;;;;;4749:9;4781:26;1835:44000:41;;4781:26:16;;5218:410;1835:44000:41;;-1:-1:-1;;;5389:18:16;;:8;-1:-1:-1;;;;;1835:44000:41;;5389:18:16;1835:44000:41;5389:18:16;1835:44000:41;;5389:18:16;;;;;;;-1:-1:-1;5389:18:16;;;5218:410;-1:-1:-1;;;;;;1835:44000:41;;5421:21:16;;5417:54;;1835:44000:41;;-1:-1:-1;;;5389:18:16;1797:53:32;;;;;;5578:10:16;1797:53:32;;;1835:44000:41;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;;-1:-1:-1;;1797:53:32;;1835:44000:41;;;;1797:53:32;1835:44000:41;1797:53:32;7875:421;;;;;;;;;-1:-1:-1;7875:421:32;;8310:15;;8328:26;;;:31;8310:68;8306:146;;5218:410:16;:::o;8306:146:32:-;8401:40;;;-1:-1:-1;8401:40:32;5389:18:16;1835:44000:41;1797:53:32;-1:-1:-1;8401:40:32;8310:68;8377:1;8362:16;;8310:68;;5417:54:16;5451:20;;;-1:-1:-1;5451:20:16;5389:18;-1:-1:-1;5451:20:16;5389:18;;;;;;;;;;;;;;:::i;:::-;;;;8186:545:24;8359:365;8186:545;1704:1;;8186:545;1704:1;1835:44000:41;1704:1:24;;1835:44000:41;8540:18:24;1835:44000:41;8540:18:24;;;1835:44000:41;;8576:19:24;;;;1704:1;1835:44000:41;;-1:-1:-1;;;;;8613:28:24;;;1704:1;1835:44000:41;8659:22:24;1835:44000:41;8659:22:24;;;1835:44000:41;;;8699:11:24;1835:44000:41;;;;;8699:11:24;;1835:44000:41;;;8576:19:24;1835:44000:41;8359:365:24;;;8540:18;8359:365;;1704:1;;:::i;:::-;-1:-1:-1;;;250:1:1;;-1:-1:-1;;;1835:44000:41;1704:1:24;;808::23;250::1;;;;-1:-1:-1;;;;;;250:1:1;1704::24;;;250::1;1835:44000:41;8277:1;;;;-1:-1:-1;;;;;;8277:1:41;1704::24;;;1835:44000:41;;;;250:1:1;;;1704::24;;;;;;-1:-1:-1;;;;;;1704:1:24;;;;;808::23;;-1:-1:-1;;;;;;808:1:23;1704::24;;;808::23;8338:10:41;;-1:-1:-1;;;;;;8338:10:41;1704:1:24;;;8338:10:41;;1704:1:24;;8359:365;1835:44000:41;;8359:365:24;;;;;;:::i;16296:213:39:-;1835:44000:41;16374:24:39;;16370:103;;1835:44000:41;;16296:213:39;:::o;16370:103::-;16421:41;;;;;16452:2;16421:41;1835:44000:41;;;;16421:41:39;;41416:381:41;41600:1;41624:3;1835:44000;;41603:19;;;;;-1:-1:-1;;;;;1835:44000:41;;41711:11;;;;:::i;:::-;8277:1;41643:80;;;;;;1835:44000;;-1:-1:-1;;;41643:80:41;;41691:4;41643:80;;;1835:44000;-1:-1:-1;;;;;1835:44000:41;;;;;;;;;;;;;-1:-1:-1;;1835:44000:41;;;;;;-1:-1:-1;;41643:80:41;;;;;;;;41624:3;;1835:44000;;41588:13;;41643:80;;;41600:1;41643:80;;;:::i;:::-;1835:44000;;;;;41643:80;;;41603:19;;41781:8;41603:19;;;41781:8;:::i;1835:44000::-;;;;;:::i;:::-;8277:1;1835:44000;;8277:1;;;:::i;:::-;1835:44000;;;;;;;;;;:::i;:::-;;;-1:-1:-1;1835:44000:41;;;;;;;;;:::o;:::-;;;;;;;;;;;;;6701:34;;;;;;;;;;;-1:-1:-1;;;;;6701:34:41;;;;;;;;;;;;;;;;;;;:::i;:::-;1835:44000;8277:1;1835:44000;;8277:1;;;:::i;:::-;6701:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;;;6701:34:41;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;1835:44000;;;;;;;;6701:34;;1835:44000;6701:34;;;;;;8338:10;;6701:34;;;;;;;;;;;;;;;:::o;:::-;1835:44000;;;;;6701:34;1835:44000;6701:34;;1835:44000;;;6701:34;;;;;;;;;:::i;:::-;1835:44000;;6701:34;;;;;;;;;;39195:1968;;;;39370:32;39382:19;1835:44000;;39382:19;:::i;:::-;39370:32;:::i;:::-;39507:11;1835:44000;39442:1;;1835:44000;39486:32;;-1:-1:-1;;;;;1835:44000:41;;;39486:32;-1:-1:-1;;;;;1835:44000:41;;;;39486:32;;;;6394:42;39486:77;;39442:1;39574:1307;39615:3;1835:44000;;39594:19;;;;;39653:12;;;;;:::i;:::-;39697:11;;;;;;:::i;:::-;8277:1;39743:34;39805:43;;39743:34;:43;;:34;;;1835:44000;;;;;;;;25737:15;1835:44000;;;;;;;39743:43;1835:44000;;;8277:1;;;;;;;;39805:43;;39507:11;39805:43;;1835:44000;;;;;;;;39805:43;;;;;;;;;;39442:1;39805:43;;;39615:3;-1:-1:-1;39860:4:41;-1:-1:-1;;;;;1835:44000:41;;;39805:60;39801:120;;40816:43;1835:44000;;;;;;40816:54;1835:44000;;;;;;;;39935:479;;39615:3;-1:-1:-1;;1835:44000:41;;-1:-1:-1;;;39805:43:41;40468:255;;;-1:-1:-1;;;;;1835:44000:41;;;40468:255;;;1835:44000;;;6701:34;;;1835:44000;6701:34;;;1835:44000;;;;-1:-1:-1;1835:44000:41;6701:34;;;1835:44000;;6701:34;;;1835:44000;40468:255;1835:44000;6701:34;;;40468:255;6701:34;40468:255;40428:295;;;;:::i;:::-;;;;;;:::i;:::-;-1:-1:-1;;;;;;1835:44000:41;;;;;;25737:15;1835:44000;;;;;;;;40816:34;;1835:44000;40816:54;1835:44000;39579:13;;;39935:479;1835:44000;;-1:-1:-1;;;39805:43:41;40023:286;;;-1:-1:-1;;;;;1835:44000:41;;;40468:255;40023:286;;1835:44000;;;6701:34;;;1835:44000;6701:34;;;1835:44000;;;;6701:34;;;1835:44000;39442:1;6701:34;;;1835:44000;;;40023:286;;40468:255;;1835:44000;;;39983:326;;1835:44000;;40023:286;1835:44000;6701:34;;;40023:286;6701:34;40023:286;39983:326;;;;:::i;:::-;;;:::i;:::-;;1835:44000;39935:479;;;;;;;;;39801:120;39892:14;;;39442:1;39892:14;39507:11;39442:1;39892:14;39805:43;;;;;;;;;;;;;;:::i;:::-;;;;39594:19;;;;;;;;;;40922:32;;;:::i;:::-;40969:13;39442:1;40984:23;;;;;;1835:44000;;;39442:1;41087:69;1835:44000;;;8277:1;;;;;;;41087:69;;39507:11;41087:69;;;:::i;:::-;;1835:44000;;41105:25;-1:-1:-1;;;;;1835:44000:41;41087:69;;;;;;;;39195:1968;:::o;41087:69::-;;;;;39442:1;41087:69;;;;;;:::i;:::-;;;;;:::i;41009:3::-;41047:19;;1835:44000;41047:19;;;:::i;:::-;;41028:38;;;;:::i;:::-;;;;;;:::i;:::-;;1835:44000;40969:13;;39486:77;;;;;1586:1:24;;;;;;;;;:::i;:::-;-1:-1:-1;;;250:1:1;;808::23;;;;-1:-1:-1;;;;;;808:1:23;;;1835:44000:41;1586:1:24;;808::23;-1:-1:-1;;;1586:1:24;;;808::23;;;;;;1586::24;;;808::23;1835:44000:41;8277:1;-1:-1:-1;;;;;;8277:1:41;1586::24;;;1835:44000:41;1586:1:24;;:::o;:::-;;;;;;;;;;;;:::i;:::-;1835:44000:41;;;250:1:1;;1704::24;;;;-1:-1:-1;;;;;;1704:1:24;1586;;;1704;808::23;;-1:-1:-1;;;;;;808:1:23;1586::24;;;808::23;8338:10:41;;-1:-1:-1;;;;;;8338:10:41;1586:1:24;;;8338:10:41;1586:1:24;;;:::i;7480:700::-;;7932:241;7480:700;7932:241;1835:44000:41;;;;;;;;7820:17:24;7656:247;7820:17;;;;7656:247;7819:42;7820:29;:17;;1835:44000:41;7820:29:24;:::i;:::-;7819:42;:::i;:::-;7875:18;;;1835:44000:41;;;;;;7656:247:24;;;7875:18;7656:247;;;:::i;:::-;;1835:44000:41;;7656:247:24;;;;;;:::i;:::-;1835:44000:41;7990:19:24;;1704:1;1835:44000:41;;8027:28:24;1704:1;8027:28;;;1704:1;-1:-1:-1;;;;;1835:44000:41;;;1704:1:24;8073:22;1835:44000:41;8113:11:24;1835:44000:41;8073:22:24;;;1835:44000:41;;;;;;8142:17:24;;1835:44000:41;;;7932:241:24;;;7875:18;7932:241;;;:::i;41968:872:41:-;;;;42099:28;1835:44000;;42099:28;:::i;:::-;42191:11;1835:44000;42170:32;;-1:-1:-1;;;;;1835:44000:41;;;42170:32;-1:-1:-1;;;;;1835:44000:41;;42170:32;:77;;6394:42;42170:77;;-1:-1:-1;42299:3:41;1835:44000;;42278:19;;;;;42336:11;42687:56;:43;42336:11;1835:44000;42336:11;;;:::i;:::-;8277:1;42480:34;42381:291;42480:43;;:34;;;1835:44000;;;;;;;;25737:15;1835:44000;;;;;;;42480:43;1835:44000;;-1:-1:-1;;;42381:291:41;;;;-1:-1:-1;;;;;1835:44000:41;;;42381:291;;;1835:44000;;;6701:34;;;1835:44000;6701:34;;;1835:44000;;;;6701:34;;;1835:44000;39442:1;6701:34;;;1835:44000;;6701:34;;;42381:291;6701:34;42381:291;42362:310;;;;:::i;:::-;;;;;;:::i;:::-;-1:-1:-1;;;;;;1835:44000:41;;;;;;25737:15;1835:44000;;;;;42687:34;1835:44000;42687:43;1835:44000;;-1:-1:-1;;;;;;1835:44000:41;;;;42687:56;1835:44000;42263:13;;42278:19;-1:-1:-1;;1835:44000:41;;-1:-1:-1;;;42764:69:41;;42278:19;;-1:-1:-1;;;;1835:44000:41;;;;42764:69;;42191:11;42764:69;;;:::i;42170:77::-;;;;
Swarm Source
ipfs://fee52d7311955066f78324771ae7deefd5385e3abd4f8b126ddc67bfc5952067
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.